DynamoDB TTL, point-in-time recovery and global tables

How DynamoDB TTL deletes expired items (epoch seconds, days of delay, expired items still readable, service deletions in streams, replicated deletes billed), what point-in-time recovery restores and what it leaves for you to re-create on the new table, and how global tables behave in eventual (MREC) and strong (MRSC) consistency modes — conflicts, transactions, synchronized settings and limits.

markdownreferencev4M6B0-D7N1stage: referencetrust: officialservice: dynamodbinterface: anyDynamoDB TTLtime to live epoch secondsexpired items still returnedTTL delayTTL stream service deletionPITRpoint-in-time recoveryRecoveryPeriodInDaysRestoreTableToPointInTimerestored table missing settingsglobal tablesMRECMRSCmulti-Region strong consistencylast writer winsReplicatedWriteConflictExceptionReplicationLatencyglobal table transactionswitness Regionsettings synchronized replicas

Created 18 Oct 2026 · Modified 23 Oct 2026 · 4 versions

**TTL is a cleanup job, not a deadline. PITR restores into a new table that lacks many of the original's settings. Global tables replicate asynchronously by default, with last writer wins.** All three surprise code that assumes otherwise.

Time to live (TTL)

  • The attribute must be a Number holding Unix epoch seconds (not milliseconds). Items whose attribute isn't a Number are ignored. Enable TTL on the table and name the attribute (SDK TimeToLiveSpecification: { Enabled, AttributeName }).
  • Items are deleted "typically within a few days" after they expire. Until then they are still returned by GetItem, Query and Scan, and can be updated. Filter them out:
import { DynamoDBDocumentClient, QueryCommand } from "@aws-sdk/lib-dynamodb";
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";

const ddb = DynamoDBDocumentClient.from(new DynamoDBClient({}));
const now = Math.floor(Date.now() / 1000);
const res = await ddb.send(new QueryCommand({
  TableName: "Sessions",
  KeyConditionExpression: "pk = :pk",
  FilterExpression: "attribute_not_exists(expiresAt) OR expiresAt > :now",
  ExpressionAttributeValues: { ":pk": "user#42", ":now": now },
}));
console.log(res.Items?.length);
  • Setting the TTL to a future time, or removing it, before deletion un-expires the item. To refresh an item that may already be gone, add a condition expression such as attribute_exists(pk).
  • TTL deletes consume no write capacity in the Region where the item expired. They also remove the item from GSIs and LSIs.
  • In DynamoDB Streams, TTL deletes appear as service deletions, not user deletes. A REMOVE-triggered Lambda function (patterns/dynamodb-streams-to-lambda.md) fires for them too, so tell them apart if the business logic differs. The exact identity fields aren't on the fetched page.
  • Global tables replicate TTL deletes, and each replica Region bills them as replicated writes, which can throttle provisioned replicas. TTL isn't available on MRSC tables.

Point-in-time recovery (PITR)

  • Continuous backups with per-second restore points over a recovery period of 1–35 days (default 35; SDK PointInTimeRecoverySpecification: { PointInTimeRecoveryEnabled, RecoveryPeriodInDays }). Pricing is by table and LSI size, so shortening the period doesn't lower it.
  • Disabling and re-enabling PITR resets the window: at first you can restore only to LatestRestorableDateTime.
  • A restore always creates a new, independent table. The source keeps serving reads and writes, and restore time depends on size and index count, with no guarantee.
RestoredNot restored: set again on the new table
Data, GSIs, LSIs, provisioned capacity, encryption settingsAuto scaling policies, IAM policies, CloudWatch metrics and alarms, tags, Streams settings, TTL settings, PITR settings (resource policies: not stated)
aws dynamodb restore-table-to-point-in-time \
  --source-table-name Orders --target-table-name Orders-restored \
  --restore-date-time 2026-10-18T09:30:00Z \
  --billing-mode-override PAY_PER_REQUEST
  • Use --use-latest-restorable-time instead of a timestamp to restore to the latest point.
  • --global-secondary-index-override '[]' drops the GSIs, which makes the restore faster and cheaper.
  • --sse-specification-override is required for cross-Region restores. You pay for transfer out and for the new table.
  • To "restore in place", point the application at the restored table, or copy data back. Re-enable Streams, TTL and PITR on it first.
  • From a global table, the restored table is not a replica, but you can make a new global table from it.

If the table is managed by CloudFormation or the CDK, the restored table is outside the stack. Import it (reference/cloudformation/change-sets-drift-and-import.md) or treat it as a migration source.

Global tables

The consistency mode is chosen at creation and can't be changed. MREC is the default.

MREC (multi-Region eventual)MRSC (multi-Region strong)
ReplicationAsynchronous, typically ≤ 1 s; ReplicationLatency metric per Region pairSynchronous to at least one other Region before the write succeeds; RPO 0
ConflictsLast writer wins per itemConcurrent writes to an item fail with ReplicatedWriteConflictException (retryable)
Strong readsCurrent only if the item was last written in that RegionCurrent on every replica
Conditional writesEvaluated against the local copyConsistent
TransactionsAtomic only in the calling Region; other Regions can see partial resultsNot supported
RegionsAny where DynamoDB runs; add replicas any timeExactly 3: three replicas, or two plus a witness (no reads or writes, not in your account); table must be empty; no replicas added later
Not supported—TTL, LSIs, transactions; GSIs only with eventually consistent reads
StreamsAlways on, can't be disabled; per-item order keptOff by default; identical across replicas

Settings across replicas:

  • Always the same: capacity mode, write capacity and write auto scaling, key and GSI definitions, SSE type, TTL, warm throughput, on-demand maximum write throughput, and Streams on MREC.
  • Overridable per replica: read capacity and read auto scaling, table class, on-demand maximum read. A later change to the synchronized value anywhere overwrites the overrides.
  • Per replica, never synchronized: deletion protection, PITR, tags, Contributor Insights, Kinesis streaming, resource policies, and Streams on MRSC.

So enable PITR and deletion protection in each Region.

Design for MREC: make writes idempotent, avoid read-modify-write across Regions (or route each item's writes to a home Region), and don't rely on transactions or conditional writes for cross-Region invariants. Errors are in reference/dynamodb/errors.md.

Read this document as markdown — the same bytes an agent receives.