Reading35 min read·Module 3High exam weight

Amazon DynamoDB Performance

Key concepts

  • Partition key design

  • Sort key strategies

  • RCU and WCU calculations

  • On-demand vs provisioned

  • Hot partition mitigation

Overview

Amazon DynamoDB is a fully managed, serverless NoSQL key-value and document database that delivers single-digit millisecond performance at any scale. Data is stored in tables, each item is identified by a primary key, and DynamoDB automatically spreads items across internal storage units called partitions. You do not provision or patch servers; AWS handles replication across three Availability Zones, scaling, and maintenance for you.

For SAA-C03 this is a high-yield topic because scenarios test whether you can design a key schema that distributes traffic evenly, choose the right capacity mode, and right-size throughput. You should understand partition key design, sort key strategies, how read capacity units (RCU) and write capacity units (WCU) are calculated, when to use on-demand versus provisioned capacity, and how to detect and fix hot partitions (single partitions that receive a disproportionate share of traffic).

Performance Follows Key Design

DynamoDB performance depends first on the primary key. A high-cardinality partition key (a key with many distinct values) spreads traffic evenly across partitions, while a sort key enables efficient range queries within one partition key value. Capacity mode (on-demand or provisioned) controls how you pay for and scale the throughput that the key design enables.

Exam Tip

Memorize the throughput math: 1 RCU = 1 strongly consistent read per second of an item up to 4 KB (or 2 eventually consistent reads), and 1 WCU = 1 write per second of an item up to 1 KB. Round item sizes UP to the next 4 KB (reads) or 1 KB (writes). Know that on-demand removes capacity planning while provisioned with Auto Scaling is cheaper for predictable traffic, and that a hot partition is fixed by improving partition key cardinality.


Key Concepts

Partition Key Design

Choosing the Partition Key

The partition key (also called the hash key) is the attribute DynamoDB hashes to decide which physical partition stores an item. Even traffic distribution requires a key with high cardinality, meaning many distinct values that are accessed roughly evenly (for example userId or orderId). Low-cardinality keys such as a status field with only a few values concentrate requests on a few partitions and waste throughput. Aim for a key that produces a near-uniform spread of both reads and writes across all possible values.

Partition Key Cardinality

Key choiceCardinalityTraffic spreadVerdict
userId or orderIdHighEven across partitionsGood
deviceId with millions of devicesHighEvenGood
status (active, pending, done)LowConcentratedPoor
fixed string for all itemsOne valueSingle partitionAvoid

Sort Key Strategies

Adding a Sort Key

A sort key (also called the range key) is an optional second part of the primary key. With a partition key plus sort key (a composite primary key), many items can share one partition key value and are stored sorted by the sort key. This enables range queries such as begins_with, between, and greater-than, and lets you model one-to-many relationships within a single partition key. A common strategy is the composite sort key, where you concatenate attributes (for example 2026-06-17#INVOICE#123) so a single sort key supports hierarchical and prefix queries. The Query operation can target one partition key value and a range of sort keys efficiently.

Primary Key Types

TypeComponentsUniqueness ruleBest for
Simple primary keyPartition key onlyPartition key must be uniquePure key-value lookups
Composite primary keyPartition key plus sort keyCombination must be uniqueOne-to-many, range queries

RCU and WCU Calculations

Read and Write Capacity Units

Throughput is measured in capacity units. One read capacity unit (RCU) provides one strongly consistent read per second for an item up to 4 KB, or two eventually consistent reads per second. One write capacity unit (WCU) provides one write per second for an item up to 1 KB. You round item size UP to the next boundary: a 5 KB item needs 2 RCUs per strongly consistent read and 5 WCUs per write. Transactional reads and writes cost double (2 RCUs or 2 WCUs per matching unit of size).

TEXTRCU and WCU Worked Examples
Read example: 80 strongly consistent reads/sec of 6 KB items
  6 KB rounds up to 8 KB = 2 RCU per read
  80 reads x 2 RCU = 160 RCU

Same read, eventually consistent
  2 RCU / 2 = 1 RCU per read
  80 reads x 1 RCU = 80 RCU

Write example: 100 writes/sec of 2.5 KB items
  2.5 KB rounds up to 3 KB = 3 WCU per write
  100 writes x 3 WCU = 300 WCU

Transactional write: 100 writes/sec of 2.5 KB items
  3 WCU x 2 (transaction) = 6 WCU per write
  100 writes x 6 WCU = 600 WCU

Capacity Unit Cheat Sheet

OperationItem size unitCost
Strongly consistent readUp to 4 KB1 RCU
Eventually consistent readUp to 4 KB0.5 RCU
Transactional readUp to 4 KB2 RCU
Standard writeUp to 1 KB1 WCU
Transactional writeUp to 1 KB2 WCU

On-Demand vs Provisioned Capacity

Choosing a Capacity Mode

Provisioned mode means you set a target number of RCUs and WCUs, optionally with Auto Scaling that adjusts capacity between a minimum and maximum based on utilization. It is the most cost-effective choice for predictable or steady traffic. On-demand mode requires no capacity planning: DynamoDB instantly accommodates traffic and you pay per request, which suits unpredictable, spiky, or new workloads where you cannot forecast load. You can switch a table from provisioned to on-demand up to four times in a 24-hour rolling window, and from on-demand to provisioned at any time.

On-Demand vs Provisioned

DimensionOn-DemandProvisioned
Capacity planningNone requiredYou set RCU and WCU
PricingPer requestPer provisioned capacity per hour
Auto ScalingAutomatic and instantOptional target tracking
Best forSpiky or unknown trafficPredictable steady traffic
Cost at steady loadOften higherOften lower

Hot Partition Mitigation

Avoiding and Fixing Hot Partitions

A hot partition occurs when one partition key value receives far more traffic than others, so requests concentrate on a single partition and can throttle even when total table capacity looks sufficient. Adaptive capacity automatically shifts unused throughput toward busy partitions and can isolate frequently accessed items, which handles many imbalances transparently. When traffic to one logical key is unavoidably high, apply write sharding: append a calculated or random suffix (for example userId#7) to spread writes across multiple partition key values, then fan out reads across the shards. Choosing a higher-cardinality partition key from the start is the primary defense.

TEXTWrite Sharding a Hot Key
Problem: a single popular product (productId = P100) gets all the writes
  All requests hash to one partition -> throttling

Fix: add a shard suffix to spread writes
  Partition key = productId#shard
  Suffixes 0..9 chosen randomly or by hash
  Writes: P100#0, P100#1, ... P100#9  (10 partition key values)

Reads: query each shard P100#0..P100#9 and merge results
  Trade-off: more keys to read, but no single hot partition

Best Practices

TEXTDesign Guidance
1. Pick a high-cardinality partition key first
   └── Spread reads and writes evenly across many distinct values

2. Use a composite primary key for one-to-many access
   ├── Sort key enables begins_with, between, and range queries
   └── Concatenate attributes for hierarchical sort keys

3. Calculate capacity from real item sizes and request rates
   ├── Round reads up to 4 KB, writes up to 1 KB
   └── Halve RCU for eventually consistent reads

4. Match capacity mode to traffic shape
   ├── On-demand for spiky or unpredictable load
   └── Provisioned with Auto Scaling for steady, predictable load

5. Mitigate hot partitions early
   ├── Rely on adaptive capacity for mild skew
   └── Apply write sharding when one key is unavoidably hot

6. Use indexes and DAX to offload work
   └── Add a Global Secondary Index for new access patterns and DAX for read-heavy microsecond caching

Common Pitfalls

Pitfall 1: Low-Cardinality Partition Key

Mistake: Using an attribute with few distinct values (such as a status or country code) as the partition key.

Why it fails: Traffic concentrates on a handful of partitions, causing throttling while overall provisioned capacity sits unused.

Correct Approach: Choose a high-cardinality partition key such as a user, order, or device identifier so requests spread evenly across partitions.

Pitfall 2: Forgetting to Round Item Sizes

Mistake: Computing RCUs and WCUs from exact byte counts instead of rounding up to the 4 KB (read) or 1 KB (write) boundary.

Why it fails: A 5 KB item needs 2 RCUs and 5 WCUs, so under-rounding underestimates capacity and leads to throttling.

Correct Approach: Always round item size up to the next 4 KB for reads and 1 KB for writes, and double the cost for transactional operations.

Pitfall 3: Provisioned Capacity for Unpredictable Spikes

Mistake: Using fixed provisioned capacity for a brand-new or highly spiky workload.

Why it fails: Under-provisioning throttles requests during spikes, while over-provisioning wastes money during quiet periods.

Correct Approach: Use on-demand mode for unpredictable or new traffic, then move to provisioned with Auto Scaling once the traffic pattern is well understood.

Pitfall 4: Scanning Instead of Querying

Mistake: Using a Scan to find items when a partition key and sort key are available.

Why it fails: Scan reads the entire table and consumes capacity proportional to all items examined, which is slow and expensive at scale.

Correct Approach: Model access patterns so you can use Query against a partition key (and sort key range) or a secondary index instead of Scan.


Test Your Knowledge

Q

An application stores game events keyed by a partition key called eventType, which has only four possible values. Under load, requests throttle even though total provisioned capacity is high. What is the most likely cause and best fix?

AThe table region is wrong; move it closer to users
BA hot partition from low cardinality; choose a higher-cardinality partition key
CEventually consistent reads; switch to strongly consistent reads
DMissing encryption; enable encryption at rest
Q

A table serves 50 strongly consistent reads per second of items that are 9 KB each. How many read capacity units should the architect provision?

A50 RCU
B150 RCU
C100 RCU
D450 RCU
Q

A startup is launching a new feature with completely unpredictable traffic that could spike suddenly. They want zero capacity planning and are willing to pay a premium per request. Which configuration fits best?

AProvisioned capacity with a high fixed RCU and WCU
BProvisioned capacity with Auto Scaling
COn-demand capacity mode
DA larger instance class for the table


Quick Reference

Limits and Facts

DynamoDB Limits and Facts

ItemValue
Maximum item size400 KB including attribute names and values
Strongly consistent read1 RCU per 4 KB
Eventually consistent read0.5 RCU per 4 KB
Standard write1 WCU per 1 KB
Transactional read or writeDouble the standard cost
Partition key (simple key)Must be unique
Partition plus sort key (composite)Combination must be unique
Capacity modesOn-demand and provisioned

Common CLI Commands

SHDynamoDB CLI
# Create a table with a composite primary key and provisioned capacity
aws dynamodb create-table \
  --table-name Orders \
  --attribute-definitions AttributeName=userId,AttributeType=S AttributeName=orderId,AttributeType=S \
  --key-schema AttributeName=userId,KeyType=HASH AttributeName=orderId,KeyType=RANGE \
  --provisioned-throughput ReadCapacityUnits=100,WriteCapacityUnits=50

# Switch a table to on-demand (pay-per-request) billing
aws dynamodb update-table \
  --table-name Orders \
  --billing-mode PAY_PER_REQUEST

# Query one partition key value with a sort key range
aws dynamodb query \
  --table-name Orders \
  --key-condition-expression "userId = :u AND begins_with(orderId, :prefix)" \
  --expression-attribute-values '{":u":{"S":"user-123"},":prefix":{"S":"2026"}}'

# Register Auto Scaling on provisioned read capacity
aws application-autoscaling register-scalable-target \
  --service-namespace dynamodb \
  --resource-id "table/Orders" \
  --scalable-dimension "dynamodb:table:ReadCapacityUnits" \
  --min-capacity 50 --max-capacity 500

Further Reading

Related services

DynamoDB