Skip to main contentSkip to user menuSkip to navigation

Amazon DynamoDB

Learn DynamoDB access-pattern modeling, partition distribution, secondary indexes, capacity modes, consistency, streams, and recovery.

40 min readIntermediate
Not Started
Loading...

What is Amazon DynamoDB?

Amazon DynamoDB is a serverless, fully managed, distributed NoSQL database that stores key-value and document data. Applications read and mutate items through primary keys, secondary indexes, and bounded APIs instead of sending arbitrary joins to a relational query planner.

DynamoDB matters when a request path needs predictable single-digit millisecond performance while traffic and data grow. AWS owns servers, partition management, replication inside a Region, maintenance, and service scaling. Your team still owns the data model, key distribution, consistency contract, capacity and quota boundaries, retry behavior, and recovery drills.

The core invariant is: every important access pattern must map to a key-based operation whose traffic remains distributed. A table with ample aggregate capacity can still throttle when one partition-key value or GSI key range receives too much work.

Known access paths

Strong fit

Use DynamoDB for high-scale request paths with known point reads, bounded range queries, conditional writes, and simple item-centered transactions.

Ad hoc relationships

Weak fit

Do not expect joins, arbitrary multi-attribute filtering, or analytical scans to remain efficient as a transactional table grows.

Serverless is not schemaless thinking

Design responsibility

AWS operates the service. The application must encode entities and relationships into keys, test skew, make retries safe, and prove restore procedures.

Build the mental model from tables, items, and keys

A table is a collection of items. An item is a collection of named attributes, similar to a row with scalar, set, list, map, or document values. Each item can have different non-key attributes, but every item must satisfy the table's primary-key schema. The complete item, including attribute names, must remain within the 400 KB item limit.

Placement and lookup

Partition key

DynamoDB hashes this value to place an item. A simple primary key contains only this attribute, so its value must be unique per item.

Ordered item collection

Sort key

With a composite primary key, items may share a partition key and are ordered by sort key. Prefixes and ranges can retrieve related items without a scan.

Unique identity

Primary key

The partition key alone, or the partition-key and sort-key pair, uniquely identifies one item and defines the direct access contract.

For a commerce table, PK = CUSTOMER#c-42 and SK = ORDER#2026-07-24T09:30:00Z#o-2048 can group one customer's orders and sort them by time. A separate order item can use PK = ORDER#o-2048 for a direct lookup. Duplicating selected facts is often intentional when it serves two bounded access patterns without a join.

Read the official core-components guide when the distinction between item identity, item collections, and secondary indexes needs a deeper walkthrough.

Design from access patterns before drawing a table

Relational modeling often starts with normalized entities and derives queries later. DynamoDB modeling reverses that sequence: list the application's reads and writes, then choose keys and indexes that answer them directly.

  1. 1

    Contract

    Name each operation

    Write concrete requests such as “get order by ID,” “list a customer's newest orders,” or “transition one order from pending to paid.”

  2. 2

    Shape

    Define bounds

    Record result count, item size, read freshness, write atomicity, peak rate, tenant isolation, and retention for every operation.

  3. 3

    Model

    Assign keys and indexes

    Map direct identity to the base key, ordered relationships to sort-key ranges, and required alternate lookup dimensions to a secondary index.

  4. 4

    Prove

    Test skew and failure

    Load-test realistic key distributions, retries, concurrency races, GSI pressure, and restore procedures before treating the schema as production-ready.

Access-pattern review

  • Prefer GetItem when the complete primary key is known.
  • Prefer Query when one partition-key value and an optional sort-key condition bound the result.
  • Treat Scan as deliberate table-wide work, not the fallback for an unmodeled request path.
  • Remember that a FilterExpression is applied after DynamoDB reads candidate items; it does not turn a broad read into a cheap key lookup.
  • Design both the base table and every GSI for high-cardinality, well-distributed partition-key values.

AWS's current DynamoDB data-modeling guide describes single-table and multiple-table foundations. Single-table design is a technique, not a requirement: use it when colocated item collections simplify real operations, not as a badge of sophistication.

Separate aggregate capacity from hot-key pressure

DynamoDB rounds write capacity by item size: one write capacity unit supports one write per second for an item up to 1 KB. A strongly consistent read of an item up to 4 KB consumes one read capacity unit; an eventually consistent read of the same size uses half as much read capacity.

Each partition is designed for up to 1,000 write capacity units and 3,000 read capacity units per second. Adaptive capacity helps uneven workloads, but it does not remove the per-partition ceiling. The same distribution problem applies independently to the base table and every GSI.

Key distribution and capacity lab

Can the hottest key range carry the writes?

Loading workload profiles, capacity-unit rules, and partition bounds.

Loading the DynamoDB workload model.

Choose capacity mode from traffic evidence

  • On-demand: pays per request and removes a configured table-level capacity target. It is a strong default for new, spiky, or unpredictable workloads, but hot key ranges, configured maximum throughput, account quotas, and rapid growth beyond warm throughput still matter.
  • Provisioned: configures RCU and WCU directly, optionally with auto scaling. It fits steady, measurable workloads when the team can manage headroom and scale before scheduled bursts.
  • Both modes: require realistic partition-key distribution, per-index monitoring, bounded clients, and diagnosis from the throttling reason rather than a generic “add capacity” response.

Use the official partition-key guidance and capacity-mode guide to verify service behavior as limits and features evolve.

Add secondary indexes only for named queries

A secondary index stores a separate, projected view of table items under another key schema. It makes an alternate query efficient, but it adds write work, storage, and a new distribution surface.

Authoritative key

Base table

Supports eventually consistent reads by default and optional strongly consistent reads for GetItem, Query, and Scan.

Same partition key

Local secondary index

Uses the base partition key with another sort key. It shares table capacity and can support strong reads, but must be created with the table and has item-collection constraints.

Alternate partition key

Global secondary index

Can use different partition and sort keys. Updates are asynchronous, reads are always eventually consistent, and its partitions and capacity are independent of the base table.

In provisioned mode, a GSI has separate RCU and WCU. If an index cannot absorb base table updates, DynamoDB can throttle the base-table write to maintain index consistency. A low-cardinality GSI partition key such as status = OPEN can therefore become hot even when the base table's customer IDs distribute perfectly.

Review AWS's read-consistency contract and GSI back-pressure guide before promising read-after-write behavior or diagnosing write throttling.

Choose consistency, correctness, and recovery together

Read consistency answers what a read may observe. Conditional writes and transactions answer whether concurrent mutations preserve business invariants. Backups answer how operators recover from a valid API call that produced the wrong business state. None of these controls substitutes for the other two.

Consistency, index, and recovery lab

Choose the contract, not just the API

Loading workload contracts and DynamoDB decision boundaries.

Loading consistency, index, and recovery scenarios.

Correctness boundaries

  • A single PutItem, UpdateItem, or DeleteItem is atomic for its item.
  • A condition expression rejects a write when the current item no longer satisfies a version, existence, state, or numeric invariant.
  • TransactWriteItems groups multiple item actions into one ACID operation that commits or cancels as a unit.
  • A strongly consistent pre-read does not lock the item. Use a condition or transaction at mutation time to prevent lost updates and invalid transitions.

Make throttles, retries, and stream delivery harmless

Transient throttling is part of the API contract. A reliable client slows down, retries only safe work, and preserves the identity of the business operation.

Bounded DynamoDB mutation and event path

The write invariant is enforced before the table changes. Stream-triggered consumers still need destination-side idempotency because failed batches can be retried.

Identify

Application command

Carry a stable order, request, or event identifier so a retry refers to the same business operation.

Protect

Condition or transaction

Check the current invariant atomically and commit one item or an all-or-nothing item set.

Persist

DynamoDB table

Return success only after the write is durably persisted, or return a specific condition, transaction, quota, or throttling failure.

React

Stream consumer

Process change records with an idempotency boundary so a retried Lambda batch does not repeat a charge, email, or projection mutation.

Retry rules

  • Use AWS SDK retry behavior or bounded exponential backoff with jitter for throttling and retryable service failures.
  • Inspect ThrottlingReason and the affected resource ARN; table capacity, key-range pressure, and GSI pressure require different fixes.
  • BatchWriteItem is not atomic as a whole. Retry only returned UnprocessedItems, not every request that already succeeded.
  • Use conditional writes, transaction client tokens where supported, and stable operation IDs to make repeated requests safe.
  • Send exhausted work to a visible failure path with enough context to replay it deliberately; do not retry forever inside a request thread.

DynamoDB Streams captures item changes for event-driven processing. A Lambda trigger retries a failed batch, so the consumer must be idempotent even when the source record itself has a stable event ID.

Treat backups as a recovery workflow, not a checkbox

Point-in-time recovery continuously captures table recovery points at per-second granularity for a configurable period from 1 to 35 days. A restore creates a new table; it does not rewind the current table in place. The team must validate the restored data and deliberately reapply or verify settings such as IAM policies, auto scaling, alarms, streams, TTL, tags, deletion protection, and PITR itself.

On-demand backups are useful for named milestones and longer-lived snapshots. Replicas, global tables, GSIs, and Streams improve availability or propagate changes, but they can also propagate an accidental delete or corrupt write. They are not independent rollback history.

  1. 1

    Stop

    Detect and contain

    Block the bad writer, capture the failure window, and preserve logs before another deployment or repair changes the evidence.

  2. 2

    Recover

    Restore to a new table

    Choose a point before the mutation and restore without consuming source-table provisioned throughput.

  3. 3

    Prove

    Validate data and settings

    Check representative keys, counts, indexes, encryption, access policy, streams, TTL, alarms, and application compatibility.

  4. 4

    Resume

    Cut over and reconcile

    Redirect traffic deliberately, reconcile valid writes after the restore point, monitor the new table, and keep a rollback path until the incident is closed.

See the official PITR guide and restore behavior when writing the runbook.

Put the contracts into focused code

The first example turns named access patterns into concrete primary-key, range-query, and transaction requests. The key strings make entity type and relationship intent visible during debugging.

Model key-based order access patterns

BatchWriteItem may return a partially processed result. This loop resubmits only the unprocessed work with capped exponential backoff and jitter.

Retry unprocessed batch writes

A stream-triggered Lambda can see a batch again after failure. The final example transactionally claims the stream event ID and creates one outbox intent. A downstream worker can then retry that stable intent without silently losing or duplicating the derived work.

Process stream records idempotently

Keep the key grammar, condition expressions, retry policy, and restore procedure under version control. A DynamoDB table can be operationally healthy while the application's access contract is still incorrect.

No quiz questions available
Could not load questions file
Spotted an issue or have a better explanation? This page is open source.Edit on GitHub·Suggest an improvement