Amazon DynamoDB

Amazon DynamoDB is a fully managed, serverless NoSQL key-value and document database. It delivers single-digit millisecond latency at any scale, with built-in horizontal sharding, multi-AZ replication, and optional global replication — and no servers, patches, or storage capacity to manage.


Key Features:


Common Use Cases:


Data Modeling Principles:


Service Limits & Quotas:


Pricing Model:


Code Example — PutItem and Query:


import boto3
from boto3.dynamodb.conditions import Key

table = boto3.resource("dynamodb", region_name="us-west-2").Table("Orders")

table.put_item(Item={
    "pk": "CUSTOMER#1042",
    "sk": "ORDER#2026-04-21#A-482",
    "total": 129.95,
    "status": "SHIPPED",
})

resp = table.query(
    KeyConditionExpression=Key("pk").eq("CUSTOMER#1042") & Key("sk").begins_with("ORDER#2026-04"),
)
for item in resp["Items"]:
    print(item["sk"], item["status"], item["total"])
  

Transactional Write Across Two Items:


client = boto3.client("dynamodb", region_name="us-west-2")

client.transact_write_items(TransactItems=[
    {"Update": {
        "TableName": "Accounts",
        "Key": {"pk": {"S": "ACCT#A"}},
        "UpdateExpression": "SET balance = balance - :amt",
        "ConditionExpression": "balance >= :amt",
        "ExpressionAttributeValues": {":amt": {"N": "100"}},
    }},
    {"Update": {
        "TableName": "Accounts",
        "Key": {"pk": {"S": "ACCT#B"}},
        "UpdateExpression": "SET balance = balance + :amt",
        "ExpressionAttributeValues": {":amt": {"N": "100"}},
    }},
])
  


Common Interview Questions:

What's the difference between a GSI and an LSI?

LSI (Local Secondary Index) shares the partition key with the base table but has a different sort key, must be defined at table creation, and shares throughput with the base table — limited to 10 GB per partition key. GSI (Global Secondary Index) has independent partition and sort keys, can be added or dropped anytime, has its own throughput, and is eventually consistent. Use GSIs almost always.

How do you avoid hot partitions?

Choose high-cardinality partition keys (user ID, not country code), avoid time-only keys for writes (shard with random suffix or hash prefix), and rely on adaptive capacity to handle short bursts. For genuinely uneven access patterns, write-shard the key (USER#123#0..15) and fan-out reads.

When use single-table design?

When you have known, bounded access patterns and want one network round-trip per query. Multiple entity types share one table with composite keys (pk: USER#123, sk: ORDER#...) so a single Query returns related items. Adds modeling complexity; not worth it for simple CRUD.

On-demand vs. provisioned capacity?

On-demand: zero capacity planning, instant scaling, pay per request — best for unpredictable, spiky, or new workloads. Provisioned: cheaper at steady traffic, supports reserved capacity discounts, requires auto-scaling configuration. Switch from on-demand to provisioned once traffic is predictable.

What is DynamoDB Streams used for?

Ordered change log per partition of all item writes (24-hour retention). Consumed by Lambda for event-driven processing — denormalize into search indexes, fan out to other services, or trigger workflows. Each Stream record contains old and new images of the item.

How do Global Tables resolve conflicts?

Last-writer-wins based on the latest write timestamp at the originating region. There's no application-level conflict resolution hook. Design partition keys so concurrent writes to the same item from multiple regions are rare (e.g., region-affinitized customers).

When to add DAX?

For read-heavy workloads where p99 latency matters more than cost (microseconds vs. single-digit milliseconds), and where the working set fits in DAX cluster memory. DAX is a write-through cache; writes go to DynamoDB first, then update the cache. Doesn't help write-heavy workloads.


DynamoDB is the default choice on AWS when you need predictable performance at any scale and your access patterns can be modeled as key-value or document lookups.