Skip to content

Rate limiting

Control how fast you read and write to DynamoDB. Rate limiting helps you stay within your provisioned capacity and avoid throttling errors.

Key features

  • Fixed rate for known workloads
  • Adaptive rate that adjusts based on throttling
  • Metrics to track usage

Getting started

Why rate limit?

DynamoDB charges for capacity units. When you exceed your provisioned capacity, DynamoDB throttles your requests - they fail with a ProvisionedThroughputExceededException.

Rate limiting helps you:

  • Stay within budget - Don't accidentally burn through capacity
  • Avoid throttling - Smooth out traffic spikes
  • Share fairly - Multiple processes can share capacity without fighting

Fixed rate

Use FixedRate when you know exactly how much capacity to use. The rate stays constant unless you change it.

from pydynox import DynamoDBClient
from pydynox.rate_limit import FixedRate

# Limit to 50 read capacity units per second
client = DynamoDBClient(rate_limit=FixedRate(rcu=50))

# Limit both read and write
client = DynamoDBClient(rate_limit=FixedRate(rcu=50, wcu=25))

# Allow bursts up to 200 RCU
client = DynamoDBClient(rate_limit=FixedRate(rcu=50, burst=200))

FixedRate is good for:

  • Batch jobs with predictable throughput
  • Background processes that shouldn't use too much capacity
  • Sharing capacity between multiple workers

Adaptive rate

Use AdaptiveRate when you don't know the right rate, or when capacity varies. It automatically adjusts based on throttling feedback.

from pydynox import DynamoDBClient
from pydynox.rate_limit import AdaptiveRate

# Set max capacity, it figures out the rest
client = DynamoDBClient(rate_limit=AdaptiveRate(max_rcu=100))

# With write limit too
client = DynamoDBClient(rate_limit=AdaptiveRate(max_rcu=100, max_wcu=50))

# With custom min (won't go below this)
client = DynamoDBClient(rate_limit=AdaptiveRate(max_rcu=100, min_rcu=10))

How adaptive rate works:

  1. Starts at 50% of max rate
  2. When throttled, reduces by 20%
  3. When no throttle for 10 seconds, increases by 10%
  4. Never goes below min or above max

AdaptiveRate is good for:

  • Variable workloads
  • Shared tables where capacity changes
  • When you're not sure what rate to use

Advanced

Checking metrics

You can see how much capacity you've used and how many times you were throttled:

from pydynox import DynamoDBClient
from pydynox.rate_limit import FixedRate

rate_limit = FixedRate(rcu=50, wcu=25)
client = DynamoDBClient(rate_limit=rate_limit)

# After some operations...
for i in range(10):
    client.put_item("users", {"pk": f"USER#{i}", "name": f"User {i}"})

# Check metrics
print(f"RCU used: {rate_limit.consumed_rcu}")
print(f"WCU used: {rate_limit.consumed_wcu}")
print(f"Throttle count: {rate_limit.throttle_count}")

This is useful for:

  • Monitoring your application
  • Tuning your rate limits
  • Debugging throttling issues

FixedRate parameters

Parameter Type Default Description
rcu int None Read capacity units per second
wcu int None Write capacity units per second
burst int None Burst capacity (defaults to rate value)

About burst: DynamoDB allows short bursts above your provisioned rate. If you set burst=200 with rcu=50, you can temporarily read at 200 RCU, but you'll need to slow down afterward to stay within your average.

AdaptiveRate parameters

Parameter Type Default Description
max_rcu int Required Maximum RCU per second
max_wcu int None Maximum WCU per second
min_rcu int 1 Minimum RCU (won't go below this)
min_wcu int 1 Minimum WCU (won't go below this)

When to use each

Scenario Recommendation
Known, steady workload FixedRate
Variable workload AdaptiveRate
Batch jobs FixedRate with high burst
Shared capacity AdaptiveRate
Multiple workers FixedRate, divide capacity by worker count

Rate limiting with batch operations

Rate limiting works with batch operations too. The rate limiter tracks capacity used by each batch and waits if needed:

from pydynox import BatchWriter, DynamoDBClient
from pydynox.rate_limit import FixedRate

client = DynamoDBClient(rate_limit=FixedRate(wcu=50))

with BatchWriter(client, "users") as batch:
    for i in range(1000):
        batch.put({"pk": f"USER#{i}", "name": f"User {i}"})
    # Rate limiter ensures we don't exceed 50 WCU

Tip

When doing bulk writes, combine rate limiting with batch operations. This gives you both efficiency (fewer API calls) and control (predictable throughput).