Guide · System design
How Amazon DynamoDB Works: Partitions, Capacity and Durability
25 min readUpdated By Saket Bhatnagar
Researched and drafted with AI, reviewed and edited by Saket Bhatnagar.
In short
- DynamoDB architecture splits each table into partitions, slices of data chosen by hashing the partition key (the field you look items up by). Request routers, the front-door servers, send each read and write to the partition that owns that key.
- Each partition is kept as three copies, called replicas, in different Availability Zones (separate data centre sites in one region). One replica leads, and a write is confirmed once two of the three have saved it to their logs.
- Capacity is counted in units. One read unit is one fully up-to-date read of up to 4 KB a second, and one write unit is one 1 KB write a second. Each partition tops out at 3,000 read units and 1,000 write units a second (AWS docs, as of 19 October 2026).
- Burst capacity (saved-up spare units), adaptive capacity (lending a busy partition the table's spare units) and automatic splits absorb most uneven traffic. One item that needs more than a partition's limit still needs a new key design.
- Beginners can stop after the section on avoiding hot partitions. Engineers then get what most explainers skip. The ThrottlingReasons field in an error names a hot partition for you. Point-in-time recovery (PITR), which restores a copy of a table as it was at an earlier moment, is off until you enable it. And the October 2025 outage in us-east-1, AWS's Northern Virginia region, shows durable is not the same as reachable.
What goes wrong when a DynamoDB table throttles while half empty?
A DynamoDB table can refuse writes while it still has spare capacity, because limits apply to each partition, not only to the whole table. Seeing why takes a short tour of DynamoDB architecture: how data is split, copied and metered.
Picture a common setup. An online sticker shop in Ahmedabad keeps carts and orders in Amazon DynamoDB, a database that AWS (Amazon Web Services) runs as a cloud service. For its Uttarayan kite festival sale, the team adds a live sales counter to the home page. The setup is made up, but the problem is real.
Every cart change and every order updates a single item called SALES_TODAY, which holds today's running totals. At 8 pm on sale day, a sticker pack goes viral, and that one item gets about 1,400 updates a second. The table is set for 5,000 writes a second and is using only 2,100.
Carts start failing anyway. The on-call engineer sees a wall of throttling errors. Throttling means DynamoDB refuses a request because it is over a limit, and the request has to be retried later. The table dashboard shows 42 percent use.
This guide follows the same shop from start to end. You will see where the hidden limit sits, why the table total hid it, and the small key change that fixes it.
What is Amazon DynamoDB?
Amazon DynamoDB is a managed NoSQL database from AWS: you store and fetch items by key, and AWS runs every server for you. It launched as a public service in 2012, according to a 2022 paper by its engineers.
NoSQL here means it is not a classic database of tables joined with SQL queries. A table holds items, and an item is one record, like one cart. Each item has a primary key, the value that finds it.
The primary key has one or two parts. The partition key decides where the item lives. An optional sort key orders items that share a partition key. The shop's carts use the cart id as the partition key. Orders use the customer id as the partition key and the order time as the sort key.
The name causes confusion. In 2007 Amazon published a paper on an internal store called Dynamo. The 2022 DynamoDB paper says the service shared most of that name but little of its architecture. If you have read about Dynamo's hash ring, treat DynamoDB as a different machine.
How does DynamoDB architecture work?
DynamoDB architecture has four main parts, per the 2022 paper: request routers, a metadata service, storage nodes and an autoadmin service. Routers receive every call, metadata knows where keys live, storage holds data, and autoadmin keeps the fleet healthy.
When the shop's API server saves a cart, it never talks to a storage server directly. It sends the request to the regional endpoint, where a request router picks it up. The router authenticates the caller and checks permissions. Then it finds which partition owns the key and forwards the request there: to the leader for writes and for strong reads (reads that reflect every earlier successful write).
Read the diagram from left to right. Notice that the autoadmin box never touches a customer request. It works in the background, watching partition health and replacing unhealthy replicas and failing hardware.
The main parts of DynamoDB
Drag to exploreEvery request passes through a router. Storage nodes hold the partitions, and autoadmin heals them in the background.
Diagram connections:
- Shop API servers to Request router (Read or write a key)
- Request router to Metadata service (Which partition?)
- Request router to Storage nodes (Forward to a replica)
- Autoadmin service to Storage nodes (Heal and replace)
- Storage nodes to S3 log archive (Archive logs)
- Shop API servers: Save carts, place orders
- Request router: Checks the caller, finds the partition
- Metadata service: Maps key ranges to storage nodes
- Storage nodes: Hold partition replicas on SSDs
- Autoadmin service: Replaces unhealthy replicas and hardware
- S3 log archive: Keeps old write-ahead logs for restore
The metadata service needs care, because every request depends on it. Routers once fetched and cached a whole table's routing map. The paper says that when routers started with empty caches, lookups could spike and strain the metadata store. DynamoDB then built MemDS, an in-memory store spread over many servers, to serve those lookups.
How does DynamoDB decide which partition stores an item?
DynamoDB runs the partition key through an internal hash function, and the result picks the partition. The paper adds that each partition holds one contiguous, non-overlapping slice of the table's key range, so a key always lands in one place.
A hash function turns any text into a big number that looks random. The same input always gives the same number. Nearby keys like cart-1001 and cart-1002 get very different numbers, so they spread out.
Picture a potato cold storage near Agra. Each farmer has a code, and a chart at the gate says which block of codes goes to which chamber. To find a farmer's sacks, the clerk reads the code, checks the chart and walks to one chamber. Here is how the picture maps:
- The farmer code is the hashed partition key.
- Each chamber is a partition, holding one block of codes.
- The chart at the gate is the metadata service's routing map.
- The clerk who reads the chart is the request router.
Where the picture breaks: a chamber is one room, but a partition is three copies on three machines. And DynamoDB redraws the chart by itself when a chamber gets too full or too busy.
Items that share a partition key, like all orders of one customer, sit together, sorted by the sort key. DynamoDB calls that group an item collection.
Here is a toy version of the router's lookup. Real DynamoDB uses its own internal hash, which AWS does not publish. This toy uses MD5, a standard hash, and four made-up ranges.
import bisect
import hashlib
# Upper end (exclusive) of each partition's hash range: 4 partitions
RANGE_ENDS = [2**126, 2**127, 3 * 2**126, 2**128]
def hash_key(partition_key):
digest = hashlib.md5(partition_key.encode()).digest()
return int.from_bytes(digest, "big") # a number from 0 to 2**128 - 1
def find_partition(partition_key):
h = hash_key(partition_key)
return bisect.bisect_right(RANGE_ENDS, h) # first range that ends above h
for key in ["cart-1001", "cart-1002", "SALES_TODAY"]:
print(key, "-> partition", find_partition(key))Run it with Python 3 and you should see three lines: cart-1001 goes to partition 0, cart-1002 to partition 2 and SALES_TODAY to partition 1. MD5 gives the same numbers on every run and every machine.
What just happened? hash_key turned each key into a 128-bit number. bisect_right found the first range whose upper end is above that number, which is the owning partition. SALES_TODAY lands on the same partition every time, however busy it gets.
When does DynamoDB add partitions?
The developer guide says DynamoDB adds partitions when one fills up with data, or when you raise provisioned throughput beyond what the current partitions can serve. Provisioned throughput is the read and write units you reserve in advance. The paper adds a third trigger: a partition that stays busy past a threshold is split for consumption.
A split cuts one range into two, and the routing map gains a line. The docs say this happens in the background while the table stays available. Your code never sees or picks partitions. Your lever is the key you choose.
How does DynamoDB keep three copies of every write?
Each partition is stored as a replication group of three replicas in different Availability Zones. One replica is the leader, and a write is confirmed once two of the three have saved it to their write-ahead logs.
The three replicas pick a leader using Multi-Paxos, a consensus protocol (a set of rules that lets machines agree even when some fail). The leader holds a lease, a time-limited right to lead, and keeps renewing it.
A write-ahead log is an append-only list of changes, saved before the main data is touched, so a crash can be replayed. Each storage replica keeps this log plus a B-tree, a sorted structure that makes key lookups fast.
Follow one cart update from the API server to the reply. Each box is one step, with who talks to whom.
One write to a DynamoDB partition
Drag to exploreNotice the reply waits for two of the three replicas to log the write, not for all three.
Diagram connections:
- Send UpdateItem to Look up the partition
- Look up the partition to Send to the leader
- Send to the leader to Copy the log record
- Copy the log record to Two of three have logged it
- Two of three have logged it to Reply 200 OK
- Send UpdateItem: Shop API → Request router
- Look up the partition: Request router → Metadata (cached)
- Send to the leader: Request router → Leader replica
- Copy the log record: Leader → Two follower replicas
- Two of three have logged it: Follower → Leader: the write is durable
- Reply 200 OK: Leader → Request router → Shop API
Strongly consistent and eventually consistent reads
The paper says only the leader serves writes and strongly consistent reads, while any replica can serve eventually consistent reads. A strongly consistent read reflects every write that succeeded before it. An eventually consistent read may be slightly behind.
Eventually consistent is the default for GetItem, Query and Scan, the calls that fetch one item, a key's items or the whole table. It also costs half as much. Reads from global secondary indexes (extra copies of the table keyed by another attribute) and from streams (a feed of changes) are always eventually consistent.
The shop uses strong reads only at checkout, where a stale cart could charge the wrong amount.
What are read and write capacity units in DynamoDB?
A read capacity unit (RCU) is one strongly consistent read a second of an item up to 4 KB, or two eventually consistent reads. A write capacity unit (WCU) is one write a second of an item up to 1 KB. Bigger items round up, so a 3 KB write costs 3 units.
You pay for capacity in one of two modes. In provisioned mode you set RCUs and WCUs in advance. In on-demand mode you pay per request, and the docs say a table instantly takes up to double its previous peak. Going past double within 30 minutes can still throttle. The shop used provisioned mode at 5,000 WCUs.
Pause and predict before reading on. The table had 2,900 spare write units a second, yet writes to one item failed. Which limit did the counter hit?
It hit the partition ceiling. AWS's partition key guide says every partition is designed to deliver at most 3,000 read units and 1,000 write units a second, as of 19 October 2026. The page names no capacity mode, so plan for it in both.
SALES_TODAY was one small item, so each update cost one write unit, and the item lived in one partition. That partition could never take more than 1,000 writes a second. The sale sent 1,400. The other partitions sat almost idle, so the table total looked healthy.
Item size shrinks the ceiling further. The same page gives the maths: a 20 KB item costs 5 read units per strongly consistent read, so one item can serve about 600 such reads a second.
How does a partition count units? The paper describes token buckets: counters that refill at a fixed rate, where each request spends tokens. Each partition had one bucket for its allocation and one for bursts, plus one bucket for the whole storage node. An empty bucket means throttling.
What is adaptive capacity in DynamoDB?
Adaptive capacity is DynamoDB automatically giving a busy partition more throughput from the table's unused capacity, so uneven traffic is not throttled. The docs say it is on for every table at no extra cost, in both capacity modes.
Back at the cold storage, one chamber is crammed because many farmers with nearby codes harvested early. Next door, a chamber is half empty. A sensible manager lets the crowded chamber use the spare room for the season. The building's total space has not changed.
DynamoDB has several tools of this kind. Each one covers a different shape of uneven traffic.
- Burst capacity. The docs say DynamoDB currently keeps up to 300 seconds of unused capacity for short spikes. They add that it may spend this on background maintenance, and that the details might change.
- Adaptive capacity. A hot partition gets a bigger share, as long as traffic stays within the table total and the partition maximum.
- Isolating hot items. The docs say DynamoDB rebalances so busy items do not share a partition. For one very busy item, it might give that item a partition to itself.
- Split for consumption. The paper says a partition that stays busy is split at a point chosen from the key distribution it has observed.
- On-demand mode. You pay per request, and the paper says DynamoDB scales such tables by splitting partitions for consumption.
The two sources tell this story in different words, so here is who says what. The 2022 paper says early DynamoDB divided capacity equally between partitions, so hot keys were throttled while others sat idle. It reports that adaptive capacity, which was best-effort, eliminated over 99.99 percent of throttling caused by skewed access.
The paper then says DynamoDB replaced adaptive capacity with global admission control. There, request routers keep local token buckets topped up by a central service that tracks the whole table. The developer guide, as of 19 October 2026, still calls the feature adaptive capacity.
Which tool handles a busy partition
Drag to exploreFollow the answers from the top. Check the one-item case first, because no tool lifts the partition ceiling for one key.
Diagram connections:
- Writes jump on one partition to One item over the ceiling?
- One item over the ceiling? to Change the key design (Yes)
- One item over the ceiling? to Short spike? (No)
- Short spike? to Spend burst capacity (Yes)
- Short spike? to Boost the hot partition (No)
- Boost the hot partition to Isolate or split (Still hot)
- Writes jump on one partition: Like the SALES_TODAY counter at 8 pm
- One item over the ceiling?: Over 1,000 write units a second on one key
- Change the key design: Only your code can fix this case
- Short spike?: Seconds, not minutes
- Spend burst capacity: Up to 300 seconds of saved unused units
- Boost the hot partition: Borrow from the table's spare capacity
- Isolate or split: Move hot items apart, split busy ranges
The table puts the four tools side by side. Each cell comes from the developer guide or the 2022 paper.
| Tool | What it handles | How fast | What it cannot do |
|---|---|---|---|
| Burst capacity | Short spikes on one partition | Instant, from saved units | Last beyond about 300 seconds of savings, or push one partition past 3,000 read or 1,000 write operations a second |
| Adaptive capacity | Lasting skew between partitions | Instant, the docs say, at no extra cost | Go above the table total or the partition maximum |
| Split for consumption | A busy key range in one partition | Usually minutes, the paper says | Help one hot item or keys written in sequence |
| On-demand mode | Traffic you cannot forecast | Up to double the previous peak at once | Make one item faster than one partition |
How do you avoid hot partitions in DynamoDB?
You avoid hot partitions by choosing a partition key with many distinct values that are used evenly. When one logical thing gets too many writes, you spread it over several keys with a suffix.
Carts were never the problem. Thousands of cart ids spread across all the partitions. The counter was the problem: one key taking every write.
The docs call the fix write sharding. You add a number to the key, so one counter becomes ten items, SALES#2026-01-14#0 to SALES#2026-01-14#9. Each write picks one at random. To show the total, you read all ten and add them up.
import random
SHARDS = 10
def add_sale(table, day, amount):
key = f"SALES#{day}#{random.randrange(SHARDS)}" # one of 10 items
table.update_item(
Key={"pk": key},
UpdateExpression="ADD total_rs :a, orders :one",
ExpressionAttributeValues={":a": amount, ":one": 1},
)
def day_total(table, day):
keys = [{"pk": f"SALES#{day}#{n}"} for n in range(SHARDS)]
items = [table.get_item(Key=k).get("Item", {}) for k in keys]
return sum(item.get("total_rs", 0) for item in items)Here table is a Table object from boto3, the official AWS library for Python. add_sale shows the order path; cart changes would use the same pattern. ADD increases a number inside the item and starts from 0 if the item or attribute does not exist yet. The read side pays the price: ten reads instead of one.
We ran this block against moto 5.1.14, an in-memory fake of DynamoDB, with boto3 1.40.55. After 1,400 calls of add_sale with 250 rupees each, day_total returned 350000. In our run the ten items held between 118 and 156 orders each; yours will differ, because the suffix is random.
Pass amounts as an int or a Decimal. Given 249.5, boto3 refuses with a TypeError saying float types are not supported. Moto imitates the API only, so this run proves the code, not how real partitions behave.
What just happened? The random suffix spread about 1,400 writes a second into about 140 per item. In our simulation of 1,000 such seconds, the busiest item stayed under 200 writes in a second, far below the 1,000 ceiling.
Ten different keys can still land on one partition, because you cannot see the hash. Hot item isolation is the backstop. The docs say adaptive capacity rebalances so busy items do not share a partition, which reduces the chance of throttling. The shop also caches the total on the home page for five seconds, so reads stay small.
One trap remains. An AWS database blog post warns that after a server error you cannot tell whether an ADD applied. AWS SDKs retry such errors by default, so the counter may count twice. That is fine for a display counter, but not for money.
A few more habits keep partitions calm:
- Use ids with many values, such as cart id or customer id, as partition keys.
- Avoid a date or a status alone as a partition key, because one value takes all of today's traffic.
- Use a calculated suffix, such as a number worked out from the order id, when you also need to fetch single items directly.
- Know that a local secondary index (a second sort order inside each partition key) changes the rules. With one on the table, the docs say adaptive capacity will not split an item collection across partitions.
- Load-test sale traffic before the sale, and watch throttles per key, not just per table.
How do you prove that a hot partition caused DynamoDB throttling?
You prove it from the error itself. Since 15 August 2025, every throttled DynamoDB request carries a ThrottlingReasons field, and a reason ending in KeyRangeThroughputExceeded means one partition went over its own limit.
Each reason joins three parts: the resource (table or index), the operation (read or write) and the limit type. As of 19 October 2026, the docs list four limit types:
- ProvisionedThroughputExceeded: a provisioned table or index went over the capacity you set.
- KeyRangeThroughputExceeded: one partition went over the internal per-partition limit, usually because of a hot key.
- MaxOnDemandThroughputExceeded: an on-demand table went over the maximum you set for it.
- AccountLimitExceeded: an on-demand table and its indexes went over the per-table maximum set at the account level.
For the shop's counter, the error would carry TableWriteKeyRangeThroughputExceeded and the table's ARN, its full AWS resource name. The matching metric in CloudWatch, AWS's monitoring service, is WriteKeyRangeThroughputThrottleEvents.
Read the reason
Log ThrottlingReasons from every throttling error. A KeyRange reason points at a partition, not at your table settings.
Find the key
Turn on Contributor Insights, a CloudWatch feature that lists top keys, in throttled-keys mode. It reports only the most throttled keys, so you pay only while throttling happens.
Match the metric
Graph WriteKeyRangeThroughputThrottleEvents next to consumed write capacity. Rising key-range throttles while total use stays well under the table limit is the hot partition signature.
Rule out scans
If no single key stands out, look for sequential access, such as a long Scan or writes in scan order. The docs name both as key-range throttling causes.
Raising the table's provisioned capacity does not lift the 1,000 write unit ceiling on one item's partition. Fix a single hot item with the key design shown above.
How does DynamoDB make sure confirmed writes are not lost?
DynamoDB protects confirmed writes with write-ahead logs on three replicas, log archives in Amazon S3, checksums, and background checks that the copies match. The 2022 paper describes each layer, and each one catches a different failure.
Durability means a confirmed write survives. Availability means you can reach the data right now. They are different promises, and the outage below shows the gap.
A disk or server fails
Replication groups on that node drop to two copies. The paper says healing a storage replica can take several minutes, so the leader adds a log replica, which takes only a few seconds.
Logs leave the node
Write-ahead logs are archived to Amazon S3, an object store designed for 11 nines (99.999999999 percent) of durability. Unarchived logs are typically a few hundred megabytes.
Bits flip silently
Every log entry, message and log file carries a checksum, a short fingerprint of the data. A change in transit shows up as a fingerprint that no longer matches.
Copies drift apart
A scrub process checks that all three replicas hold the same data. It also compares live replicas with a copy built offline from the archived logs.
Code has a bug
The core replication protocol is specified in TLA+, a language for describing designs precisely. The paper says model checking caught subtle bugs before the code went into production.
Your own code deletes the wrong rows
Point-in-time recovery (PITR) restores the table as it was at an earlier moment, always into a new table. It is off by default, and as of 19 October 2026 you set its recovery period between 1 and 35 days.
The paper says a log replica starts fast because only the recent write-ahead logs are copied to it, without the B-tree. In the diagram, see how the S3 archive feeds both the scrub checks and restores.
Layers that keep DynamoDB writes safe
Drag to exploreThree replicas protect fresh writes. The S3 archive protects history and feeds both the scrub checks and restores.
Diagram connections:
- Leader replica to Two follower replicas (Log records)
- Leader replica to Log replica (When a replica fails)
- Two follower replicas to S3 log archive (Archive old logs)
- S3 log archive to Scrub job (Rebuild and compare)
- S3 log archive to Point-in-time recovery (Snapshots plus logs)
- Leader replica: Sends each log record to the others
- Two follower replicas: Other Availability Zones, same data
- Log replica: Added in seconds when a replica fails
- S3 log archive: Checksummed log files
- Scrub job: Compares live copies with a rebuilt one
- Point-in-time recovery: Into a new table, within your 1-35 day window
The paper says backups and restores do not affect the table's performance or availability, because they are built from the logs archived in S3.
Check your own tables now. Run aws dynamodb describe-continuous-backups with --table-name and your table's name. A new table shows PointInTimeRecoveryStatus as DISABLED; once enabled, it shows ENABLED and a RecoveryPeriodInDays value such as 35.
The docs add one more detail, as of 19 October 2026: the latest restorable time is typically five minutes before now. So the newest few minutes cannot be restored yet.
What the October 2025 outage teaches
AWS's post-event summary says DynamoDB in us-east-1, its Northern Virginia region, had increased API error rates. It lasted from 11:48 pm PDT (US Pacific time) on 19 October to 2:40 am PDT on 20 October 2025. In Indian time, that is 12:18 pm to 3:10 pm on 20 October.
The summary traces it to a latent race condition in DynamoDB's DNS management system. DNS is the internet's phone book, turning a name like an endpoint into server addresses. A race condition is a bug where the result depends on which of two jobs finishes first.
One DNS Enactor, running late, applied a much older plan over a newer one. Another Enactor's clean-up then deleted that old plan, which left the regional endpoint with an empty DNS record.
Clients could not open new connections to DynamoDB in the region. Customers with global tables, which keep copies of a table in other regions, could still use their replicas there, though with prolonged replication lag to and from us-east-1. The summary does not mention data loss.
So for a shop like ours, three in-region copies would keep the data durable, but no one could reach it by name. That is a different failure, with a different fix.
How do you explain DynamoDB architecture in a system design interview?
Explain it from the partition outward: how keys find partitions, how each partition stays safe, and how capacity follows the traffic. Use one concrete hot key to make it real.
Start with the data model
Tables, items, partition key and sort key. Show one real key, like a customer id with orders sorted by time.
Draw the request path
Client, request router, metadata lookup, then the storage node that leads the partition.
Explain the replication group
Three replicas in different zones, one leader picked by Multi-Paxos, writes confirmed by two of three.
Cover reads
Strong reads go to the leader. Eventually consistent reads can hit any replica and cost half as much.
Bring in capacity
Name the per-partition ceiling, then burst, adaptive capacity and splits. Close with write sharding for one hot item.
Finish with failure
Log replicas, archived logs, checksums and point-in-time recovery. Then say how you would survive a region going dark, for example with global tables.
Questions people ask
- Does DynamoDB use consistent hashing?
- Not in the Dynamo ring sense. DynamoDB hashes the partition key, and the 2022 paper says each partition holds one contiguous slice of the key range, which splits as the table grows. Dynamo instead placed keys on a ring of nodes. For your design the effect is similar: well-spread keys spread the load, and one key always lands in one partition.
- How many copies of my data does DynamoDB keep?
- The 2022 paper says each partition lives in a replication group of three replicas, placed in different Availability Zones of one region. A write is confirmed once two of them have saved it to their write-ahead logs. Global tables add full copies in other regions on top of that, if you turn them on.
- Is DynamoDB strongly consistent?
- It can be, per read. Reads are eventually consistent by default and may miss a write from a moment ago. Set ConsistentRead to true on GetItem, Query or Scan against a table or local secondary index to get every earlier successful write. Global secondary index and stream reads are always eventually consistent.
- What is a hot partition in DynamoDB?
- A hot partition is one partition getting far more traffic than the others. The docs say each partition delivers at most 3,000 read units and 1,000 write units a second. Adaptive capacity, hot item isolation and splits fix most cases, but one very busy item needs a new key design, such as a suffix.
- Should I use on-demand or provisioned capacity?
- Use on-demand when traffic is new, spiky or hard to forecast, and you would rather pay per request. Use provisioned when traffic is steady and predictable, and you want to set the read and write units yourself. Neither mode lifts the per-partition ceiling, so key design still matters.
- Can DynamoDB lose data?
- It is designed so that a confirmed write is not lost. Writes sit in the logs of at least two replicas before the reply, and logs are archived to S3 with checksums and checked by scrubs. It cannot protect you from your own bad deletes, so enable point-in-time recovery for tables that matter.
- What happens when a DynamoDB leader replica fails?
- The other replicas elect a new leader with Multi-Paxos. The paper says the new leader must wait for the old leader's lease to expire, which takes a couple of seconds, before serving traffic. Because any replica can serve eventually consistent reads, the remaining replicas can still serve them meanwhile.
Sources and further reading
- Elhemali et al., Amazon DynamoDB: A Scalable, Predictably Performant, and Fully Managed NoSQL Database Service (USENIX ATC 2022), paper page with PDF
- Werner Vogels, Amazon's Dynamo (2007), with the full SOSP 2007 Dynamo paper
- DynamoDB Developer Guide: Partitions and data distribution
- DynamoDB Developer Guide: Best practices for designing and using partition keys (3,000 read and 1,000 write units per partition)
- DynamoDB Developer Guide: Burst and adaptive capacity
- DynamoDB Developer Guide: On-demand capacity mode
- DynamoDB Developer Guide: Read consistency
- DynamoDB Developer Guide: Using write sharding to distribute workloads evenly
- boto3 reference: Table update_item (ADD starts from 0 when the item does not exist)
- AWS Database Blog: Implement resource counters with Amazon DynamoDB (31 March 2023)
- DynamoDB Developer Guide: Diagnosing throttling (ThrottlingReasons and key-range metrics)
- AWS Database Blog: Enhanced throttling observability in Amazon DynamoDB (15 August 2025)
- DynamoDB Developer Guide: Enable point-in-time recovery
- AWS: Summary of the Amazon DynamoDB Service Disruption in the Northern Virginia (US-EAST-1) Region, October 2025