Topic 4.4
DynamoDB & ElastiCache
In one line
DynamoDB is a serverless key-value/document database that delivers single-digit-millisecond reads at any scale if — and only if — you design keys around your access patterns; ElastiCache gives you managed Redis/Valkey or Memcached for caching and fast shared state.
Think of it like this
DynamoDB is a massive filing cabinet where you must know the drawer (PARTITION KEY) and can then flip through folders in order (SORT KEY). It's instant if you know the drawer, and painful if you want 'every folder mentioning Mumbai' across all drawers.
Key ideas
- 01
Every item has a PRIMARY KEY: a PARTITION KEY (hashed to decide which partition stores it) plus an optional SORT KEY (ordering within that partition).
Queryfetches items by partition key and a sort-key condition — fast and cheap.Scanreads the whole table — slow and expensive; avoid it on hot paths. - 02
DESIGN FROM ACCESS PATTERNS: list the exact queries first ('get order by id', 'list a customer's orders newest-first'), then choose keys — e.g. PK =
CUSTOMER#42, SK =ORDER#2026-09-15#789. GLOBAL SECONDARY INDEXES provide alternate keys for other access patterns. Relational-style normalization and joins don't exist. - 03
HOT PARTITIONS: a low-cardinality partition key (like
statusor today's date) funnels traffic into one partition and throttles. Choose high-cardinality keys that spread load evenly. - 04
CAPACITY: ON-DEMAND bills per request with no planning; PROVISIONED (with autoscaling) is cheaper for steady, predictable load. Other built-ins: TTL to expire items, Streams for change events (feeding Lambda), transactions, and point-in-time recovery.
- 05
ELASTICACHE runs managed Redis/Valkey (rich data structures, replication, persistence) or Memcached (simple, multi-threaded cache). The common pattern is CACHE-ASIDE: read from cache, on miss read the database and populate the cache with a TTL. Put it in private subnets; enable cluster mode and Multi-AZ replicas for production Redis.
Code & diagrams
aws dynamodb create-table --table-name orders \
--attribute-definitions AttributeName=pk,AttributeType=S AttributeName=sk,AttributeType=S \
--key-schema AttributeName=pk,KeyType=HASH AttributeName=sk,KeyType=RANGE \
--billing-mode PAY_PER_REQUEST
aws dynamodb put-item --table-name orders --item '{
"pk": {"S": "CUSTOMER#42"},
"sk": {"S": "ORDER#2026-09-15#789"},
"total": {"N": "1499"},
"status": {"S": "PAID"}
}'
# A customer's orders from September, newest first — a Query, not a Scan
aws dynamodb query --table-name orders \
--key-condition-expression "pk = :c AND begins_with(sk, :m)" \
--expression-attribute-values '{":c":{"S":"CUSTOMER#42"},":m":{"S":"ORDER#2026-09"}}' \
--no-scan-index-forwardExplain it without notes
Why is Scan considered an anti-pattern for request-path queries in DynamoDB?
What causes a hot partition, and how do you avoid it?
Practice
Design DynamoDB keys for a chat app needing: (a) all messages in a room, newest first, paginated; (b) all rooms a user belongs to.
When would you pick DynamoDB over RDS Postgres, and vice versa?
Trade-offs
- ↔
DynamoDB scales effortlessly with no servers to manage, but you trade query flexibility — new access patterns may require new indexes or a data migration. Caching with ElastiCache cuts database load and latency but introduces invalidation and staleness problems you must design for.
Done when you can
I design DynamoDB keys from the access patterns, and avoid Scans on hot paths.
I can recognise and prevent a hot partition.
I know on-demand vs provisioned capacity trade-offs.
I can implement cache-aside with ElastiCache and choose sensible TTLs.