AWS Marketplace

Implementing SaaS subscription pricing models in AWS Marketplace

This post is Part 3 of a four-part series on SaaS pricing models in AWS Marketplace.

In the previous blog we covered the options for a subscription pricing model. In this post, we focus on implementing the pricing models that were presented.

Software as a service (SaaS) sellers in AWS Marketplace need to meter customer usage accurately so buyers are billed only for what they consume. The metering integration is where most implementation questions arise: how to report usage hourly, how to handle tiered pricing boundaries, and how to avoid common metering errors.

In this post, learn how to implement fixed-rate and tiered SaaS subscription pricing in AWS Marketplace with sample Python code for accurate usage metering and billing.

This is the third post in a series on SaaS pricing in AWS Marketplace. For background on when to choose subscription pricing over contract pricing, refer to the previous post.

Prerequisites

Before setting up metering for fixed or tiered usage pricing, make sure the following prerequisites are in place:

  • AWS Marketplace onboarding is completed and AWS Identity and Access Management (IAM) is set up, including any required roles and permissions.
  • A SaaS product listing has been created in AWS Marketplace using usage-based pricing or a contract with consumption.
  • One or more billing dimensions have been defined for the listing.
  • At least one active subscription to the listing exists.
  • Python is installed, and an integrated development environment (IDE) is configured for testing and running scripts.

In this post, we use usage-based pricing as the pricing model for all examples. To illustrate different usage scenarios, we demonstrate fixed-rate usage using pricing dimensions Standard and Premium and tiered usage using Tier1, Tier2, and Tier3.

Subscribing to the product

Metering records require an active subscription. While the product is in Limited state, subscribe using the listing owner account or a separate test account added to the allowlist. Set pricing to a nominal value ($0.001) during testing to avoid unnecessary charges before launch. The examples later in this post use a separate test account to run through the full end-to-end flow: subscribe, report usage, and verify billing.

Metering frequency

We recommend reporting usage on an hourly basis, batching up to 25 records per request. This gives customers granular visibility of usage and cost. If there is no usage to report for an hour, submit a record with a quantity of 0 to avoid gaps in billing history.

Aggregate all usage for the hour and submit after the hour has completed. After it’s submitted, a record for a customer, dimension, and hour can’t be amended. If a buyer unsubscribes, submit all unreported usage within 1 hour of the unsubscribe-pending notification.

For SaaS subscription best practices when configuring your product to meter usage, refer to Configuring metering for usage with SaaS subscriptions in the AWS Marketplace Seller Guide.

Fixed-rate consumption pricing

Fixed-rate pricing works well when usage patterns are uniform. Each unit of consumption is charged at a consistent rate, regardless of volume.

A Standard API request is priced at $0.01 per call. This rate applies whether the customer makes a single request or 100,000 requests. Fixed-rate pricing supports multiple dimensions, each with its own unit price.

The following table shows a fixed-rate pricing example.

Dimension Description Cost/unit
Standard Standard API request $0.01
Premium Premium API request $0.05

Implementing metering for fixed-rate pricing

To implement, ensure the usage-based listing is in Limited state with appropriate pricing dimensions. We created Standard and Premium as the pricing dimensions for our SaaS product.

We will use a script to submit usage records with the following key fields:

  • LicenseArn – Unique identifier for the customer’s agreement, obtained from the ResolveCustomer API response during the registration flow
  • CustomerAWSAccountId – The AWS account ID of the customer
  • Dimension – Pricing dimension applied (Standard or Premium)
  • Quantity – Total usage for the reporting hour
  • Timestamp – Hourly timestamp corresponding to usage

Note: Starting June 1, 2026, new SaaS products must include LicenseArn in each UsageRecord to support Concurrent Agreements. If you have an existing product listed before this date, your current integration will continue to work, but we recommend adopting LicenseArn to support multiple active agreements under the same account. The LicenseArn value is returned by the ResolveCustomer API during buyer registration.

Copy the script below and save it as fixed_rate_metering.py

Note: Update LICENSE_ARN, CUSTOMER_ID, DIMENSION, and QUANTITY with your values.

python

import boto3

  from datetime import datetime, timezone




  LICENSE_ARN = "arn:aws:license-manager::123456789012:license:l-xxxxxxxx"

  CUSTOMER_ID = "123456789012"

  DIMENSION = "Standard"  # or "Premium"

  QUANTITY = 100




  marketplace = boto3.client('meteringmarketplace', region_name='us-east-1')




  marketplace.batch_meter_usage(

      UsageRecords=[{

          'LicenseArn': LICENSE_ARN,

          'CustomerAWSAccountId': CUSTOMER_ID,

          'Timestamp': datetime.now(timezone.utc),

          'Dimension': DIMENSION,

          'Quantity': QUANTITY

      }]

  )




  print(f"Billed {QUANTITY} units for {DIMENSION}")

Run the script: python3 fixed_rate_metering.py

The script will display an output similar to the following when run successfully:

Billed 100 units for Standard.

For production, persist usage data in a durable store such as Amazon DynamoDB and automate hourly submissions so no records are lost during network or application outages. Sellers can view usage and billing data under Marketplace Insights in AWS Partner Central within 24 hours of submitting metering records.

Tiered consumption pricing

Tiered consumption pricing applies lower rates as customer usage grows. The tiers are represented by separate pricing dimensions, and cumulative usage must be tracked for each customer.

The following table shows a tiered pricing example. With these pricing dimensions, Tier1 applies to the first 10,000 requests, Tier2 applies after 10,000 requests, and Tier3 applies for requests above 50,000.

Dimension Description Cost/unit
Tier1 0–10,000 requests $0.02
Tier2 10,001–50,000 requests $0.01
Tier3 50,001+ requests $0.005

AWS Marketplace doesn’t calculate pricing tiers based on cumulative usage. The SaaS application must implement logic to track consumption across the billing period, split new usage across tier boundaries, and submit a separate metering record for each relevant tier.

Implementing metering for tiered pricing

Tiered pricing requires the application to determine current usage, so new usage is allocated to the correct tier.

We will use a DynamoDB table, `customer-usage-totals`, to store per-tier consumption. Before submitting metering records to AWS Marketplace, the script looks up existing tier usage in the table, splits new usage over any tier boundaries it crosses, and submits a separate metering record for each applicable tier.

For example, if the buyer has consumed 9,900 requests and a new batch of 200 requests arrives, the script splits the usage: 100 requests reported against Tier1 (0–10,000) and 100 requests reported against Tier2 (10,001–50,000). Each tier is submitted as a separate metering record.

We first create a DynamoDB table named `customer-usage-totals` with partition key `customer_id` (String) and sort key `billing_period` (String).

After you create the DynamoDB table, copy the script below and save as tiered_metering.py. Update LICENSE_ARN, CUSTOMER_ID, NEW_USAGE, TIER1_LIMIT, and TIER2_LIMIT with your values.

The DynamoDB table will incur charges based on your chosen capacity mode (on-demand or provisioned), storage, and data transfer. For testing purposes, on-demand mode with minimal data will result in minimal costs. Remember to delete the table when testing is complete to avoid ongoing charges.

Run the script: python3 tiered_metering.py

python
import boto3
from datetime import datetime, timezone

LICENSE_ARN = "arn:aws:license-manager::123456789012:license:l-xxxxxxxx"
CUSTOMER_ID = "123456789012"
NEW_USAGE = 100
TIER1_LIMIT = 10000
TIER2_LIMIT = 50000

dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
marketplace = boto3.client('meteringmarketplace', region_name='us-east-1')
table = dynamodb.Table('customer-usage-totals') # Amazon DynamoDB Composite key: (customer_id, billing_period)

billing_period = datetime.now(timezone.utc).strftime('%Y-%m')

# Step 1: Read per-tier consumption
item = table.get_item(
    Key={'customer_id': CUSTOMER_ID, 'billing_period': billing_period}
).get('Item', {})

tier1 = int(item.get('tier1_consumed', 0))
tier2 = int(item.get('tier2_consumed', 0))

# Step 2: Split new usage across tiers
tier1_new = max(0, min(NEW_USAGE, TIER1_LIMIT - tier1))
tier2_new = max(0, min(NEW_USAGE - tier1_new, TIER2_LIMIT - tier1 - tier2))
tier3_new = NEW_USAGE - tier1_new - tier2_new

# Step 3: Submit one metering record per tier that received usage
records = [
    {'LicenseArn': LICENSE_ARN, 'CustomerAWSAccountId': CUSTOMER_ID,
     'Timestamp': datetime.now(timezone.utc), 'Dimension': dim, 'Quantity': qty}
    for dim, qty in [("Tier1", tier1_new), ("Tier2", tier2_new), ("Tier3", tier3_new)]
    if qty > 0
]

if records:
    marketplace.batch_meter_usage(UsageRecords=records)

# Step 4: Update per-tier consumption
table.update_item(
    Key={'customer_id': CUSTOMER_ID, 'billing_period': billing_period},
    UpdateExpression='ADD tier1_consumed :t1, tier2_consumed :t2, tier3_consumed :t3',
    ExpressionAttributeValues={':t1': tier1_new, ':t2': tier2_new, ':t3': tier3_new}
)

print(f"Billed {NEW_USAGE} units (Tier1: {tier1_new}, Tier2: {tier2_new}, Tier3: {tier3_new})")

The script will display output like the following when run successfully:

Billed 100 units (Tier1: 100, Tier2: 0, Tier3: 0)

Verify metering

To confirm metering is working correctly:

  1. Query DynamoDB to confirm that the tier counters have updated.
  2. Verify the metering API call was recorded in AWS CloudTrail.
  3. Verify usage appears in AWS Partner Central under Marketplace Insights (after 24 hours).

In production, add conditional writes on the DynamoDB usage update to handle concurrent submissions and prevent double reporting.

Conclusion

In this post, we covered two subscription pricing patterns: fixed-rate for uniform consumption and tiered for volume-based discounts. We created two metering scripts: a fixed-rate script that submits usage for a single dimension and a tiered script that tracks cumulative consumption in DynamoDB and splits usage across tier boundaries. Accurate metering is designed to bill buyers only for what they consume.

To get started:

  1. Choose the pricing model that fits your product: fixed-rate pricing for predictability or tiered pricing for volume discounts.
  2. Create your AWS Marketplace listing with the appropriate pricing dimensions.
  3. Implement metering using the patterns in this post.
  4. Test end-to-end while the listing is in Limited state to verify the application is submitting usage records correctly and billing is showing as expected.

For other posts in this series:

For help with your implementation, contact your AWS representative or refer to Getting support for AWS Marketplace. For more resources, refer to the AWS Marketplace Seller Guide.

About Authors

Kevin Kennedy

Kevin Kennedy is a Marketplace Specialist Solutions Architect at AWS, where he supports buyers and sellers to list and transact in AWS Marketplace. He is passionate about applying technology to solve business challenges and create meaningful outcomes for customers. Outside of work, Kevin enjoys traveling and spending time with his family.

YokeTong Tan

YokeTong Tan is a Partner Solutions Architect at Amazon Web Services (AWS) in Singapore. In his current role, he collaborates with Global System Integrators operating in the ASEAN region and AWS Partners in the Philippines to drive cloud innovation. He supports the partners as a trusted advisor to develop and implement scalable, well-architected solutions. Outside of work, he enjoys family time and gaming.

Judy Chai

Judy Chai is a Partner Solutions Architect at Amazon Web Services (AWS) who is passionate about creating innovative cloud solutions that drive business transformation. Outside of work, Judy is an avid traveller and enjoys spending time with family.