DynamoDB Partition Key Design: Prevent Hot Partitions and Optimize Performance
Learn how to design DynamoDB partition keys correctly to prevent hot partitions and achieve maximum performance.
Related Exam Domains
- Domain 3: Design High-Performing Architectures
Key Takeaway
Choose partition keys with high cardinality and uniform access patterns. Hot partitions waste provisioned capacity and cause throttling. Use sharding techniques to distribute load.
Exam Tip
Exam Essential: "Hot partition → Throttling → Solution: High cardinality key or write sharding"
Why is Partition Key Important?
DynamoDB distributes data across physical partitions based on the hash value of the partition key.
┌─────────────────────────────────────────┐
│ DynamoDB Table │
└─────────────────────────────────────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Partition A │ │ Partition B │ │ Partition C │
│ (Hash 0-33) │ │ (Hash 34-66)│ │ (Hash 67-99)│
│ │ │ │ │ │
│ user_001 │ │ user_002 │ │ user_003 │
│ user_004 │ │ user_005 │ │ user_006 │
└──────────────┘ └──────────────┘ └──────────────┘
Per-Partition Limits
| Resource | Limit |
|---|---|
| Read Capacity | 3,000 RCU/sec |
| Write Capacity | 1,000 WCU/sec |
| Storage | 10GB |
Exam Tip
Memorize: 3,000 RCU, 1,000 WCU, 10GB per partition
What is a Hot Partition?
When requests concentrate on a specific partition, exceeding that partition's throughput limits.
Hot Partition Example
Bad design: Partition key = "date" (YYYY-MM-DD)
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 2026-01-24 │ │ 2026-01-25 │ │ 2026-01-26 │
│ │ │ │ │ HOT! │
│ Access: 1% │ │ Access: 5% │ │ Access: 94% │
│ │ │ │ │ │
│ Headroom │ │ Headroom │ │ Throttling! │
└──────────────┘ └──────────────┘ └──────────────┘
Result: All requests concentrate on today's date partition, causing throttling
Impact of Hot Partitions
- Throttling:
ProvisionedThroughputExceededExceptionerrors - Wasted capacity: Other partitions' capacity goes unused
- Performance degradation: Request delays or failures
Characteristics of Good Partition Keys
1. High Cardinality
More unique values in the partition key is better.
| Partition Key | Cardinality | Rating |
|---|---|---|
user_id | Millions | ✅ Excellent |
order_id | Millions | ✅ Excellent |
genre | 10-20 | ❌ Low |
status | 3-5 | ❌ Very low |
date | 365 | ⚠️ Low (access pattern issue) |
2. Uniform Access Patterns
Requests should be evenly distributed across key values.
Good example: user_id
- user_001: 100 requests/sec
- user_002: 95 requests/sec
- user_003: 105 requests/sec
→ Uniform distribution ✅
Bad example: celebrity_id
- celebrity_001 (popular star): 10,000 requests/sec 🔥
- celebrity_002: 10 requests/sec
- celebrity_003: 5 requests/sec
→ Concentration ❌
3. Composite Key Usage
Partition key + sort key enables more granular design.
| Design Pattern | Partition Key | Sort Key | Use Case |
|---|---|---|---|
| Orders per user | user_id | order_timestamp | Query user's order history |
| Forum posts | board_id | post_timestamp | List posts in a board |
| IoT sensors | device_id | timestamp | Time-series sensor data |
Hot Partition Solutions
Strategy 1: Write Sharding
Add random suffixes to partition keys to distribute load.
Original key: "popular_item_001"
↓
Sharded keys: "popular_item_001#shard_0"
"popular_item_001#shard_1"
"popular_item_001#shard_2"
...
"popular_item_001#shard_9"
Implementation example:
import random
def get_sharded_key(item_id, shard_count=10):
shard = random.randint(0, shard_count - 1)
return f"{item_id}#shard_{shard}"
# Write
dynamodb.put_item(
TableName='Products',
Item={
'pk': {'S': get_sharded_key('popular_item_001')},
'view_count': {'N': '1'}
}
)
# Read (aggregate all shards)
for i in range(10):
response = dynamodb.query(
TableName='Products',
KeyConditionExpression='pk = :pk',
ExpressionAttributeValues={
':pk': {'S': f'popular_item_001#shard_{i}'}
}
)
Exam Tip
Write sharding drawback: Reads must query all shards, increasing read complexity. Best suited for write-heavy workloads.
Strategy 2: Time-Based Partitioning
Use finer time granularity instead of just date.
Bad example: pk = "2026-01-26" (one hot partition per day)
Good example: pk = "2026-01-26#hour_14" (hourly distribution)
Better example: pk = "2026-01-26#14:30" (30-minute distribution)
Strategy 3: Composite Attribute Combination
Combine multiple attributes to increase cardinality.
Bad example: pk = "status" (PENDING, COMPLETED, FAILED)
→ Only 3 partitions used
Good example: pk = "status#customer_id"
→ PENDING#cust_001, COMPLETED#cust_002, ...
→ Distributed across thousands of partitions
Adaptive Capacity
DynamoDB provides a feature that automatically mitigates hot partition issues.
How It Works
- Detects hot partitions
- Redistributes spare capacity from other partitions to hot partitions
- Automatically splits partitions when needed
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Partition A │ │ Partition B │ │ Partition C │
│ Used: 200 │ │ Used: 2800 │ │ Used: 100 │
│ Limit: 1000 │ │ Limit: 1000 │ │ Limit: 1000 │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
└───────────────►│◄────────────────┘
Adaptive Capacity
Allocates extra to B
Limitations
- Not instantaneous: Takes time to detect and adjust
- Not unlimited: Works only within total provisioned capacity
- Not a substitute for design: Design improvements still necessary
Exam Tip
On exams, "Adaptive Capacity exists so partition key design doesn't matter" is a wrong answer.
Practical Design Patterns
Pattern 1: E-commerce Orders
Table: Orders
Partition key: customer_id (high cardinality)
Sort key: order_timestamp#order_id
Query patterns:
- Customer's recent orders: Query(pk=customer_id, sk begins_with "2026-01")
- Specific order lookup: GetItem(pk=customer_id, sk=timestamp#order_id)
Pattern 2: Real-time Leaderboard
Problem: Full table scan needed for overall rankings
Solution: Use GSI
- Base table: pk=user_id, sk=game_id
- GSI: pk="GAME#game_id", sk=score (descending)
- Top 100 query: Query(GSI, pk="GAME#001", Limit=100)
Pattern 3: IoT Sensor Data
Problem: Thousands of sensors sending tens of thousands of records per second
Design:
Partition key: device_id#YYYY-MM-DD-HH (hourly distribution)
Sort key: timestamp_ms
Result:
- 24 hours × 1000 sensors = 24,000 partitions
- Query individual sensor's hourly data
SAA-C03 Exam Focus Points
- ✅ Hot partition cause: "Low cardinality or uneven access patterns"
- ✅ Throttling solution: "Redesign partition key or write sharding"
- ✅ Adaptive Capacity: "Auto capacity redistribution, but not a design substitute"
- ✅ Partition limits: "3,000 RCU, 1,000 WCU, 10GB per partition"
- ✅ Composite key usage: "pk + sk for granular access patterns"
Exam Tip
Sample Exam Question: "A DynamoDB table experiences throttling when accessing data for specific dates. The partition key is date (YYYY-MM-DD). What's the best solution?" → Answer: Implement write sharding by adding random suffixes to the partition key
Frequently Asked Questions
Q: Can I change the partition key later?
No. Partition keys cannot be changed after table creation. You must create a new table and migrate the data.
Q: Can I create a table without a sort key?
Yes. Simple primary keys with only a partition key are possible. But sort keys are useful for complex query patterns.
Q: How many shards should I use?
At least the expected maximum write load divided by 1,000 WCU per partition. Example: 5,000 WCU needed → minimum 5 shards
Q: Are hot partitions a problem in On-Demand mode too?
Yes. On-Demand also has per-partition limits. Adaptive Capacity works, but may respond slowly to sudden load spikes.
Q: Do GSIs have hot partition issues too?
Yes. GSIs have their own partition structure, so GSI partition key design follows the same principles.
Related Posts
- RDS vs Aurora vs DynamoDB Selection Guide
- DynamoDB Global Tables Complete Guide
- ElastiCache (Redis vs Memcached) Comparison