Amazon DynamoDB – The Architecture Behind Single-Digit-Millisecond Scale
A practitioner-level walkthrough of how DynamoDB actually partitions data, enforces consistency, handles hot keys, and executes transactions — the internals that shape every real production data-modeling decision.
If you already know what a NoSQL key-value store is and understand basic DynamoDB terms like tables and items, this guide moves past that. We’re going straight into what actually happens when DynamoDB routes a request to a partition, how it decides between strongly and eventually consistent reads under the hood, why a poorly chosen partition key can throttle an otherwise well-provisioned table, and how Global Secondary Indexes and Streams extend the base engine without changing its core guarantees. By the end, you’ll be able to model a table for a real access pattern and defend that design in a system-design interview.
1Core Concepts
Partition Keys Decide Placement, Not Just Uniqueness
Every DynamoDB item lives on a specific physical partition — a fixed slice of storage and throughput capacity — determined by hashing the item’s partition key (also called the hash key). This is the single most consequential design decision in any DynamoDB table: the partition key isn’t just an identifier, it’s the sharding function for your entire dataset. Two items with the same partition key always land on the same partition; items with different partition keys are spread across many partitions by DynamoDB’s internal hashing.
A sort key (range key) is optional but powerful — items sharing a partition key are stored together, ordered by sort key, which is what makes range queries like “all orders for customer X between two dates” efficient without scanning the whole table.
Think of a partition key like the aisle number in a warehouse, and the sort key like the shelf position within that aisle. Look up “aisle 12, shelf 40-60” and a worker walks directly there — fast. Ask for “everything with a red label” scattered across every aisle, and someone has to walk the entire warehouse checking every shelf — that’s a table scan, and it’s exactly what a good partition key design avoids.
Capacity Modes: Provisioned vs. On-Demand
| Mode | How Capacity Works | Best For |
|---|---|---|
| Provisioned | You set Read/Write Capacity Units (RCUs/WCUs); optionally auto-scaled within bounds | Predictable, steady traffic where cost optimization matters |
| On-Demand | DynamoDB scales capacity automatically per request, billed per read/write | Spiky or unknown traffic patterns, new applications |
On-Demand mode is not infinitely elastic on a millisecond timescale — it scales to roughly double the previous peak traffic within a 30-minute window by default. A workload that spikes 10x instantly can still see throttling even in On-Demand mode if it exceeds that scaling ceiling.
2Architecture & Components
Request Router
Receives API calls, authenticates via IAM, and hashes the partition key to determine which storage partition owns the item.
Storage Nodes / Partitions
Each partition is replicated three times across different Availability Zones for durability, using Multi-Paxos-based consensus for write agreement.
Partition Metadata Service
Tracks which partitions exist and which storage nodes host them, enabling the request router to find the right destination.
Global / Local Secondary Indexes
Maintain alternate query paths on different key schemas, asynchronously (GSI) or synchronously (LSI) updated as the base table changes.
DynamoDB Streams
An ordered, time-limited log of item-level modifications, consumable by Lambda or Kinesis for event-driven architectures.
DynamoDB Accelerator (DAX)
An optional in-memory cache cluster sitting in front of DynamoDB, cutting read latency from single-digit milliseconds to microseconds for cacheable reads.
flowchart TB
APP[Application]
RR[Request Router]
subgraph PARTITIONS["Storage Partitions (replicated x3 across AZs)"]
P1[Partition 1 - Leader]
P1R1[Replica AZ-b]
P1R2[Replica AZ-c]
end
GSI[(Global Secondary Index)]
STREAM[DynamoDB Streams]
LAMBDA[Lambda Consumer]
DAX[DAX Cache Cluster]
CW[CloudWatch Metrics]
APP -->|cacheable read| DAX --> RR
APP -->|write / strong read| RR
RR -->|hash partition key| P1
P1 -->|Paxos consensus| P1R1
P1 -->|Paxos consensus| P1R2
P1 -->|async propagate| GSI
P1 -->|change events| STREAM --> LAMBDA
P1 --> CW
Note the asymmetry: writes and strongly consistent reads always go to the partition leader; DAX sits in front of the router for read-heavy, cache-friendly access patterns; and GSIs update asynchronously, meaning a GSI read can briefly lag behind the base table under heavy write load.
3Internal Working
Write Path: Consensus Before Acknowledgment
Request Routed
The request router hashes the partition key and forwards the write to that partition’s current leader replica.
Consensus Achieved
The leader replicates the write to its two peer replicas using a Paxos-based consensus protocol, requiring a majority to agree before the write is considered durable.
Write Acknowledged
Once a majority of replicas confirm, the client receives a success response — the write is now durable across multiple Availability Zones.
Streams & Indexes Updated
Change events are appended to the Streams log and propagated asynchronously to any Global Secondary Indexes.
Eventually Consistent vs. Strongly Consistent Reads
By default, a GetItem or Query call returns an eventually consistent read, which may be served by any replica — including one that hasn’t yet received the very latest write, though the propagation delay is typically well under a second. Setting ConsistentRead=true forces the read to go to the leader replica, guaranteeing you see the most recent successful write, at roughly double the read capacity cost and slightly higher latency.
It’s like asking any employee at a company’s three branch offices for the latest customer address (eventually consistent) versus insisting on calling headquarters directly, where updates are recorded first (strongly consistent). The branch offices are usually right, and always faster to reach — but right after headquarters processes a change, a branch might answer with slightly stale information for a brief moment.
“When would you deliberately choose eventually consistent reads even though strong consistency is available?” Strong answers point to cost and throughput: eventually consistent reads use half the read capacity units of strongly consistent ones, and most access patterns — a product catalog page, a social feed — tolerate a sub-second staleness window in exchange for significantly higher throughput at lower cost.
4Data Flow & Lifecycle
flowchart LR
A[Item Written] --> B[Base Table Partition]
B -->|async| C[GSI Update]
B -->|sync, same partition| D[LSI Update]
B -->|change log| E[DynamoDB Streams - 24hr retention]
E --> F[Lambda / Kinesis Consumer]
B -->|TTL attribute expires| G[Automatic Deletion]
G --> E
Time to Live (TTL) lets you mark an attribute as an expiry timestamp; DynamoDB then automatically deletes expired items in the background, at no additional write-capacity cost, typically within 48 hours of expiry. TTL deletions still appear as delete events on Streams, which is how downstream systems (e.g., archiving expired sessions to S3) stay in sync without polling.
Real Flow: Event-Driven Order Processing
An e-commerce order table uses Streams to trigger a Lambda function on every new order item written. The Lambda function updates an inventory count in a separate table and publishes an event to EventBridge — all without the order-writing service needing to know anything about inventory or notifications, decoupling the write path from downstream side effects.
5Advantages, Disadvantages & Trade-offs
Advantages
- Single-digit-millisecond latency at virtually any scale, with no manual sharding
- Fully managed — no server patching, replication setup, or failover configuration
- On-Demand mode removes capacity planning entirely for unpredictable workloads
- Streams enable clean event-driven architecture without custom change-data-capture tooling
- Transactions provide ACID guarantees across up to 100 items when needed
Disadvantages / Trade-offs
- No ad-hoc query flexibility — every access pattern must be designed for in advance via keys and indexes
- A poorly chosen partition key can create a “hot partition,” throttling requests despite adequate overall capacity
- Joins and multi-table transactions are far more limited than in relational databases
- Item size is capped at 400 KB, unsuitable for large blobs without offloading to S3
6Performance & Scalability
Adaptive Capacity and Hot Partitions
DynamoDB’s adaptive capacity feature automatically redistributes throughput toward partitions receiving disproportionate traffic, isolating a hot partition key from throttling the rest of the table — but it operates within limits, and a sufficiently skewed access pattern (e.g., one celebrity user’s ID receiving 90% of a social app’s write traffic) can still throttle even with adaptive capacity active. This is why write-heavy, highly skewed workloads often use write sharding — appending a random suffix to a hot partition key to spread writes across multiple physical partitions, then fanning in reads across the shards.
Lyft’s Ride-Matching at Scale
Lyft uses DynamoDB for latency-sensitive components of its ride-matching system, where single-digit-millisecond reads and writes at massive concurrent scale during peak ride-hailing demand directly affect how quickly a rider gets matched with a nearby driver — a workload pattern DynamoDB’s partitioned architecture is purpose-built to serve.
7High Availability & Reliability
Every DynamoDB table is automatically replicated synchronously across three Availability Zones within a region by default — there is no “Single-AZ mode” to opt out of, unlike some other AWS data services. For multi-region resilience, Global Tables replicate a table across multiple AWS Regions using a multi-active, last-writer-wins conflict resolution model.
Context
A SaaS platform serves users from both US and EU regions and needs session data to survive a full regional outage without user-visible downtime.
Decision
Enable DynamoDB Global Tables across two regions, accepting last-writer-wins conflict resolution since session data updates are simple and rarely conflict.
Consequences
Roughly doubles write costs (each write replicates to the second region) but eliminates a single-region failure as a cause of session-store downtime; the team documents that concurrent conflicting writes to the same session ID from two regions are resolved by timestamp, not merged.
8Security
IAM Fine-Grained Permissions
IAM policies can restrict access down to specific items via leading-key conditions, enabling secure multi-tenant tables without separate tables per tenant.
At Rest by Default
All tables are encrypted at rest with AWS-owned or AWS KMS customer-managed keys; encryption cannot be disabled.
VPC Endpoints
Gateway VPC endpoints allow private connectivity to DynamoDB without traversing the public internet, avoiding NAT gateway costs and exposure.
CloudTrail
Logs every control-plane and, optionally, data-plane API call for compliance and forensic review.
IAM leading-key conditions restrict which partition keys a principal can access, but they don’t inherently restrict which attributes within an item are visible — a common multi-tenant security gap is assuming key-level isolation also enforces field-level isolation, which it does not without additional application-layer checks.
9Monitoring, Logging & Metrics
| Metric | What It Tells You |
|---|---|
| ThrottledRequests | Whether requests are being rejected due to exceeded capacity on a table or partition |
| ConsumedReadCapacityUnits / ConsumedWriteCapacityUnits | Actual usage versus provisioned capacity, key input for right-sizing |
| SuccessfulRequestLatency | Real-world read/write latency percentiles, useful for SLO tracking |
| SystemErrors / UserErrors | Distinguishes AWS-side issues from client-side request mistakes |
| ReplicationLatency (Global Tables) | How far behind a replica region is from the source of a write |
Production Pattern: Hot Partition Detection
Teams enable Contributor Insights on a table to surface the specific partition keys generating the most throttled requests, turning a vague “the table is throttling” alert into an actionable “this specific customer ID is hot” finding within minutes instead of hours of guesswork.
10Deployment & Cloud Integration
IaC Table Definition
Terraform or CloudFormation defines table schema, indexes, capacity mode, and TTL settings as version-controlled, peer-reviewed code.
Serverless Integration
Lambda functions read/write via the AWS SDK, commonly fronted by API Gateway, forming a fully serverless request path with no servers to patch.
Streams-Driven Pipelines
DynamoDB Streams trigger Lambda consumers for search indexing (OpenSearch), analytics (Kinesis Firehose to S3), or cache invalidation.
Backup Automation
Point-in-time recovery (PITR) is enabled as a table setting, allowing restore to any second within the last 35 days without a manual backup schedule.
11Design Patterns & Anti-patterns
Good Patterns
- Single-table design: modeling multiple related entity types in one table using generic partition/sort key prefixes to serve several access patterns with fewer indexes
- Write sharding for known hot keys, distributing load across suffixed partition key variants
- Using Streams for decoupled, event-driven side effects instead of synchronous cross-service calls
- Sparse GSIs — indexing only items that have a given attribute, keeping the index small and cheap
Anti-patterns
- Designing the schema around entities first and access patterns second, relational-database-style
- Using Scan operations as a routine query path instead of a rare maintenance operation
- Storing large binary blobs directly as item attributes instead of referencing them in S3
- Ignoring item collection size limits when a partition key’s sort-key range grows unbounded over time
12Best Practices & Common Mistakes
Model Access Patterns Before Schema
List every query the application needs to run first, then design partition/sort keys and indexes to serve them — not the reverse.
Use Conditional Writes for Concurrency
ConditionExpression on writes prevents lost updates in concurrent scenarios without needing distributed locks.
Choosing a Low-Cardinality Partition Key
A partition key like “status” with only a few possible values (active/inactive) concentrates all traffic onto a handful of partitions regardless of table size.
Over-Indexing
Every GSI duplicates storage and consumes its own write capacity on every base table write — indexes should map directly to real, used access patterns, not “just in case” flexibility.
13Real-World & Industry Examples
Amazon.com: Shopping Cart Service
DynamoDB originated from Amazon’s internal need for a highly available, low-latency shopping cart service during peak events like Prime Day, where relational database bottlenecks under massive concurrent write load directly translated into lost sales.
Airbnb: Real-Time Pricing and Availability
Airbnb uses DynamoDB for components requiring rapid, high-throughput reads and writes tied to property availability calendars, where latency spikes directly degrade the booking experience during high-traffic periods.
Duolingo: Streak and Progress Tracking
Duolingo relies on DynamoDB to track user progress and streaks at massive scale across millions of daily active users, where single-digit-millisecond writes keep the app responsive immediately after each completed lesson.
Gaming: Leaderboards and Session State
Mobile and online games commonly use DynamoDB for session state and leaderboards, leveraging Global Tables to keep player state consistent for users connecting from different regions during global tournaments.
14Frequently Asked Questions
15Summary & Key Takeaways
Key Takeaways
- The partition key is a sharding decision, not just a unique identifier — it determines physical data placement and throughput distribution.
- Writes require majority consensus across three AZ-replicated copies before being acknowledged, giving durability without a Single-AZ mode to worry about.
- Eventually consistent reads are the default and cost half the capacity of strongly consistent reads — most access patterns can tolerate the sub-second staleness window.
- Adaptive capacity mitigates but doesn’t eliminate hot partitions — severely skewed access patterns still need write sharding.
- Access patterns must be designed for upfront, since DynamoDB has no ad-hoc query flexibility or joins the way relational databases do.
- Streams enable event-driven architectures without custom change-data-capture tooling, but only retain 24 hours of history.
- Global Tables trade roughly double write cost for multi-region resilience using last-writer-wins conflict resolution.

