11. Global tables and backups
DynamoDB · 11. Global tables and backupsTwo very different subjects share this chapter because they answer the same question from opposite ends: what happens when a region, or a person, does something you did not plan for?
Global tables
Section titled “Global tables”aws dynamodb update-table --table-name AppData \ --replica-updates '[{"Create": {"RegionName": "us-east-1"}}]'That is the whole setup. The table now exists in two regions, both writable, replicating to each other.
eu-west-1 us-east-1 ┌──────────────┐ ┌──────────────┐ │ AppData │◄───replicate───►│ AppData │ │ writable │ │ writable │ └──────────────┘ └──────────────┘ ▲ ▲ EU users write US users write locally, ~5 ms locally, ~5 ms
replication lag: typically well under a second WHAT YOU GET ✓ local read AND write latency in every region ✓ survives the loss of an entire region ✓ no failover procedure — the other region was always live ✓ per-region capacity, scaled independently
WHAT IT COSTS ✗ replicated writes are billed in EVERY region (a 3-region table = roughly 3× write cost) ✗ cross-region data transfer ✗ LAST-WRITER-WINS conflict resolution ✗ no strongly consistent reads across regions ✗ no cross-region transactions (ch 9)Last-writer-wins, and what it really means
Section titled “Last-writer-wins, and what it really means” t=0.000 eu-west writes status = "shipped" t=0.050 us-east writes status = "cancelled" t=0.400 replication settles
BOTH regions converge on "cancelled" — the write with the later timestamp. The "shipped" write is simply gone. No error, no conflict record, no merge hook. SAFE PATTERNS • per-item region affinity: a user's data is written only in their home region • append-only items (distinct sort keys) instead of mutating one shared item • conflict-free structures: counters via ADD still lose in LWW, so aggregate downstream from streams instead (ch 10)
UNSAFE PATTERNS • a global counter incremented from two regions • a shared "current state" item written from wherever the user happens to land • conditional writes as a cross-region mutex — conditions are evaluated LOCALLYThat last line deserves emphasis: a conditional write is atomic within a region. It cannot see, and cannot block, a concurrent write in another region.
Deciding whether you need it
Section titled “Deciding whether you need it” YES, GLOBAL TABLES NO, ONE REGION users on several continents one market and latency is a product requirement
regulatory presence in a a regional outage is region survivable for you
whole-region failure is a you would rather business risk you have spend the 3× write priced cost elsewhereMost applications do not need them, and the 3× write cost plus silent-write-loss risk is a high price for insurance against an event that has, historically, been rare and brief.
Backups: two mechanisms
Section titled “Backups: two mechanisms” POINT-IN-TIME RECOVERY (PITR) • continuous, automatic • restore to ANY SECOND in the last 35 days • restores to a NEW TABLE — never in place • ~$0.20 per GB-month → turn this on for every production table, today
ON-DEMAND BACKUPS • a full snapshot you trigger or schedule • retained until you delete them • no capacity consumed, no performance impact • the answer to retention beyond 35 days and to compliance requirementsaws dynamodb update-continuous-backups --table-name AppData \ --point-in-time-recovery-specification PointInTimeRecoveryEnabled=true
aws dynamodb create-backup --table-name AppData --backup-name pre-migration
aws dynamodb restore-table-to-point-in-time \ --source-table-name AppData --target-table-name AppData-restored \ --restore-date-time 2026-09-23T09:15:00ZWhat a restore does not give you
Section titled “What a restore does not give you” A RESTORED TABLE ✓ the items, as of that second ✗ auto-scaling settings — recreate them ✗ IAM policies and resource policies ✗ stream settings and their consumers ✗ TTL configuration ✗ the original table name
…and it takes MINUTES TO HOURS depending on size.So a restore is not a failover. It is a recovery from a logical mistake — a bad deploy, a bad migration, a deletion — and the runbook has to include recreating everything in that second list and repointing the application.
Deletion protection
Section titled “Deletion protection”aws dynamodb update-table --table-name AppData --deletion-protection-enabledOne flag, no cost, prevents the single most expensive human error available. Turn it on for every production table.
Export to S3
Section titled “Export to S3”aws dynamodb export-table-to-point-in-time \ --table-arn arn:aws:dynamodb:eu-west-1:…:table/AppData \ --s3-bucket analytics-exports --export-format DYNAMODB_JSON • requires PITR to be enabled • consumes NO table capacity — it reads the backup, not the table • full or INCREMENTAL exports • output: DynamoDB JSON or ION, in S3This is the right answer to nearly every analytical question about DynamoDB data:
"sum revenue by month" export → Athena "join orders with a CRM dump" export → Athena/Spark "train a model" export → S3 → wherever "find items matching a complex predicate, once" export → query in S3Running those against the live table would be a scan (chapter 4), consuming the capacity your users need. Exporting costs storage and nothing else, and the MinIO guide covers what that object storage layer is doing underneath.
Operating a global table
Section titled “Operating a global table” CAPACITY each replica has its own. a region receiving replicated writes needs capacity for BOTH its local traffic and everything the other regions send it. under-provision one replica and replication lag grows.
INDEXES GSIs must exist identically in every replica. adding one adds it everywhere, with a backfill everywhere. (ch 7)
STREAMS each region has its own stream. a consumer in every region sees LOCAL and REPLICATED changes — so naive fan-out processing runs N times for one logical event. THE DUPLICATE-PROCESSING TRAP
order written in eu-west → eu-west stream fires → send confirmation email → replicated to us-east → us-east stream fires → send it AGAIN
FIX: stamp the originating region on the item and process only records whose region matches the consumer's, or run the consumer in one region only.Watching replication
Section titled “Watching replication” ReplicationLatency per region pair. alarm on sustained growth. PendingReplicationCount records not yet applied ConsumedCapacity per replica, separatelyA disaster-recovery runbook
Section titled “A disaster-recovery runbook” SCENARIO 1 — bad deploy corrupted data → PITR restore to the second before the deploy, into a new table, repoint the application. global tables do NOT help: the corruption replicated instantly.
SCENARIO 2 — a region is unavailable → with global tables: route traffic elsewhere. nothing to restore. → without: wait, or restore a backup into another region (hours).
SCENARIO 3 — the table was deleted → deletion protection should have prevented it. if not: restore the most recent PITR window or on-demand backup, and recreate every setting that a restore does not bring back.
SCENARIO 4 — a single item was corrupted → export or restore to a scratch table, read the old value, write it back. the restore does not need to become production.Scenario 1 is the important one to internalise: multi-region protects against infrastructure, backups protect against people and code. They are not substitutes, and teams with global tables sometimes skip PITR on exactly that misunderstanding.
A recovery checklist
Section titled “A recovery checklist” □ PITR enabled on every production table □ deletion protection enabled □ on-demand backups for anything with a retention requirement beyond 35 days □ table names come from configuration, not constants □ a restore actually practised, and TIMED □ the "what a restore does not restore" list turned into a runbook □ global tables: a written statement of which region owns which items □ exports scheduled if analytics depend on themWhat to take from this chapter
Section titled “What to take from this chapter”- Global tables give active-active multi-region replication with local read and write latency and no failover procedure — for roughly N× the write cost plus transfer.
- Conflict resolution is last-writer-wins with no hooks: concurrent writes to one item from two regions mean one write silently disappears.
- Design for per-item region affinity or append-only items; never use conditional writes as a cross-region mutex, because conditions are evaluated locally.
- No strongly consistent cross-region reads and no cross-region transactions.
- PITR gives any second in the last 35 days, restoring to a new table; on-demand backups cover longer retention.
- A restore does not bring back auto-scaling, IAM, streams, TTL or the table name, and it takes minutes to hours — so it is recovery from mistakes, not failover.
- Keep table names in configuration so a restore can be adopted quickly, and enable deletion protection everywhere.
- Export to S3 (PITR-based, consuming no table capacity) is the correct route for analytics, joins and one-off complex queries.
Next: operations and the ecosystem — IAM, encryption, DAX, local development, infrastructure as code, and the tools worth knowing.