☰ All modules Tier 1 · Serverless (DynamoDB and serverless patterns) GuideCheat sheet ‹ api-gatewaysecurity-encryption ›
Contents
  1. Tables items and primary keys
  2. Read and write capacity units
  3. Capacity modes provisioned and on demand
  4. Throttling errors and retries
  5. Reading data with GetItem Query and Scan
  6. Local and global secondary indexes
  7. Writing items and conditional writes
  8. Batch operations and transactions
  9. PartiQL
  10. DAX and caching choices
  11. DynamoDB Streams and Lambda
  12. Time to Live
  13. Security and fine grained access control
  14. Serverless patterns and table operations
  15. Numbers to know
  16. Decision rules
  17. Memory hooks

Serverless (DynamoDB and serverless patterns) — Cheat Sheet (DVA-C02)

Verified against AWS documentation on 2026-10-12 · ⚠️ = changed vs older material: learn the value shown here (older practice material may say otherwise; full list in notes/dynamodb-guide.md#changed-vs-older-material) · ⚠️ unverified = AWS pages disagree or don't confirm it: don't rely on it · explanations and examples: notes/dynamodb-guide.md.

Tables items and primary keys

Topic Current facts Memory hook
Simple primary key Partition key only (HASH); no two items share a value One key, one item
Composite primary key Partition key + sort key (HASH + RANGE); the pair is unique; items sharing a partition key form an item collection sorted by sort key Folder + file name
Key schema changes Impossible after CreateTable: new access pattern → GSI, new key → new table Keys are carved in stone
Good partition key High cardinality, evenly requested (user, order or device ID); avoid status, date, country, booleans Many doors, even crowds
Item size 400 KB maximum, attribute names included Names pay rent too
Key value lengths Partition key 1–2,048 bytes; sort key 1–1,024 bytes; key types S, N or B only
Data types Scalar S, N, B, BOOL, NULL · document L, M (up to 32 levels) · sets SS, NS, BS (unique, unordered, never empty)
Dates No date type: ISO 8601 string or epoch Number (TTL needs epoch seconds)
Partition limits 3,000 RCU and 1,000 WCU per partition; 10 GB per partition 3-1-10
⚠️ Adaptive capacity Always on, free, instant: a hot partition can use more of the table's throughput (up to the partition maximum); very hot items get partitions of their own; no published partition formula Capacity follows the heat
Table lifecycle CREATING → ACTIVE; early calls → ResourceNotFoundException; recreating → ResourceInUseException Wait for ACTIVE

Read and write capacity units

Rule Current facts Memory hook
1 WCU Each second: a 1 KB block written once Write 1
1 RCU Each second: a 4 KB block read once with strong consistency, or twice with eventual consistency Read 4
Transactional Double: 2 RCU per 4 KB read, 2 WCU per 1 KB write (prepare + commit) Transactions pay twice
Order of operations Per second first → round each item up (1 KB or 4 KB) → multiply → ½ eventual or ×2 transactional → round up Seconds, round, multiply
Query sizing Sizes of all items read summed, filtered-out ones included, then rounded up once to 4 KB Query pools its items
Scan sizing Charged on items evaluated, not items returned
Batch sizing BatchGetItem and BatchWriteItem round every item separately, then add
UpdateItem sizing Larger of the before and after images
Failed condition Still consumes WCU (at least 1)
Filters and projections Shrink the response, never the capacity consumed Filters don't refund
GSI reads Always eventually consistent: ½ RCU per 4 KB of projected data
Measuring ReturnConsumedCapacity = INDEXES, TOTAL or NONE (default)
Worked example Capacity
25 writes/s of 2.5 KB items 75 WCU
90 writes/min of 3 KB items 5 WCU
8 transactional writes/s of 1.5 KB items 32 WCU
40 strongly consistent reads/s of 9 KB items 120 RCU
40 eventually consistent reads/s of 9 KB items 60 RCU
40 transactional reads/s of 9 KB items 240 RCU
Query reading 30 items of 300 bytes, strongly consistent 3 RCU

Capacity modes provisioned and on demand

Topic Current facts Memory hook
⚠️ On-demand (PAY_PER_REQUEST) Default and recommended for most workloads since the 50 % price cut of 2024-11-01; pay per request unit Pay per bite
Provisioned (PROVISIONED) RCU/WCU billed hourly + auto scaling (+ reserved capacity); for steady, predictable traffic Rent the pipe
⚠️ Switching modes Provisioned → on-demand up to 4 times per rolling 24 h; on-demand → provisioned any time Four in, any time out
New on-demand table Sustains up to 4,000 writes/s and 12,000 reads/s 4k writes, 12k reads
On-demand growth Instantly up to 2× the previous peak; beyond 2× within 30 min may throttle Double, then wait 30
⚠️ On-demand limits Per-table quota 40,000 RRU and 40,000 WRU; optional OnDemandThroughput cap → ThrottlingException On-demand is not unlimited
⚠️ Warm throughput Shown free on every table and GSI; pre-warm with WarmThroughput (charged, cannot be lowered) Warm up before the race
Provisioned quotas 40,000 RCU/WCU per table, 80,000 RCU/WCU per account per Region (adjustable)
Capacity decreases 4 at the start of each UTC day + 1 per hour (max 4 banked) = up to 27 per day
Auto scaling Target 20–90 % (console 70 %); acts after 2 consecutive minutes over target; each GSI needs its own policy Scaling is slow, burst is fast
Burst capacity Up to 300 s of unused provisioned capacity kept for spikes Five minutes in the bank
On-demand price (us-east-1) $0.625 per million WRU, $0.125 per million RRU (Standard class)
Standard-IA table class Cheaper storage, dearer requests; worth it when storage exceeds ~50 % of throughput cost; max 2 class changes per 30 days Cold storage, same speed

Throttling errors and retries

Signal Meaning and fix Memory hook
⚠️ ThrottlingReasons Each throttle names resource type + operation + limit type and the table or index ARN (since August 2025) Read the reason, not the class
…ProvisionedThroughputExceeded Over provisioned RCU/WCU → more capacity, auto scaling or on-demand
…KeyRangeThroughputExceeded Hot partition → better key, write sharding, DAX for reads, eventual reads, pre-warm Hot key
…MaxOnDemandThroughputExceeded Your on-demand cap was hit → raise it or set -1
…AccountLimitExceeded Per-table on-demand quota reached → Service Quotas increase
Index… reasons GSI back-pressure throttles base-table writes → fix the GSI's capacity or key The index pushes back
Throttling exception classes ProvisionedThroughputExceededException, ThrottlingException, RequestLimitExceeded: all HTTP 400 and retryable
Batch throttling No exception: throttled items return in UnprocessedItems / UnprocessedKeys → resend with backoff Check the leftovers
ValidationException Item over 400 KB, type mismatch, bad expression, strongly consistent read on a GSI
ResourceNotFoundException Wrong table name or Region, or table not ACTIVE yet
InternalServerError (500) Retry; a write may already have succeeded → read first or write idempotently
Throttle metrics ThrottledRequests (+1 per request), ReadThrottleEvents, WriteThrottleEvents, cause-specific …KeyRangeThroughputThrottleEvents and others
Contributor Insights THROTTLED_KEYS mode (cheap enough to leave on) or ACCESSED_AND_THROTTLED_KEYS; keys shown in plaintext Find the hot key

Reading data with GetItem Query and Scan

Topic Current facts Memory hook
GetItem One item by its full primary key; the cheapest read Know the key, get the item
Query Partition key = + optional sort key =, <, <=, >, >=, BETWEEN, begins_with; sorted by sort key One collection, in order
Scan Reads the whole table or index, then filters; for exports and batch jobs Scan = read everything
Page size 1 MB per call, measured before the filter; continue with LastEvaluatedKey → ExclusiveStartKey No key, no more pages
Limit Caps items evaluated before the filter, so pages can come back short Limit counts reads, not results
Query filter Cannot use key attributes; adds <>, OR, IN, contains, size
ScanIndexForward=false Descending sort key order (newest first)
Strong consistency Reads are eventual by default; ConsistentRead=true on tables and LSIs only, at double cost; GSIs and streams are eventual only (strong read on a GSI → ValidationException)
Parallel scan Each worker sends its own Segment + the same TotalSegments; faster, same capacity
Expression limits 4 KB per expression, 300 operators, 100 IN operands, 255 bytes per placeholder; reserved words (Status, Name, Date, Total …) need #name placeholders # for names, : for values
CLI paging --max-items + NextToken limit the output; --starting-token resumes; --page-size only splits calls Max = what you see
⚠️ CLI default page size Set per service (S3 listings 1,000); each DynamoDB call stops at 1 MB

Local and global secondary indexes

Feature LSI GSI
Partition key Same as the table Any S, N or B attribute; ⚠️ up to 4 attributes per key part
When created Only in CreateTable Any time with UpdateTable (backfill)
Limit per table 5 (hard) 20 (default quota)
Read consistency Eventual or strong Eventual only
Throughput Shares the table's capacity Own RCU/WCU (provisioned) or the table's on-demand mode
Non-projected attributes Fetched from the table at extra cost Not available
Size limit 10 GB per partition key value (item collection) None

Writing items and conditional writes

Topic Current facts Memory hook
PutItem Creates or fully replaces an item Put = replace
UpdateItem Changes named attributes; creates the item if missing (upsert) Update = upsert
Update clauses SET (assign, + or -, if_not_exists, list_append), REMOVE, ADD (numbers, sets), DELETE (set elements)
Condition expressions On PutItem, UpdateItem, DeleteItem and transaction actions; never on BatchWriteItem Guard the write
Condition failure ConditionalCheckFailedException (HTTP 400): re-read, don't retry blindly
Insert only if new attribute_not_exists(<partition key name>)
ReturnValuesOnConditionCheckFailure ALL_OLD returns the current item inside the exception, without RCU See why without reading
ReturnValues Put and Delete: NONE, ALL_OLD; Update adds UPDATED_OLD, ALL_NEW, UPDATED_NEW; free
Atomic counter SET n = n + :inc or ADD n :inc; safe under concurrency but not idempotent Counters may double-count
Optimistic locking Version attribute + condition version = :expected, incremented in the same update; Java helpers @DynamoDBVersionAttribute (SDK 1.x mapper), VersionedRecordExtension (SDK 2.x Enhanced Client) Check the version, then write
Global tables (MREC) Last writer wins across Regions, so optimistic locking doesn't protect cross-Region edits

Batch operations and transactions

Topic Current facts Memory hook
BatchWriteItem Up to 25 puts or deletes, 16 MB, 400 KB per item; no updates, no conditions; not atomic 25 to write
BatchGetItem Up to 100 items, 16 MB; read consistency chosen per table 100 to read
Partial failure UnprocessedItems / UnprocessedKeys → resend with exponential backoff
SDK batch helpers boto3 Table.batch_writer(), the Java Enhanced Client and DynamoDBMapper resend leftovers
⚠️ Transaction size 100 actions on 100 distinct items, 4 MB, one account and one Region 100 and 4
Transaction actions Put, Update, Delete, ConditionCheck; one action per item
Transaction cost 2× capacity, consumed even when the transaction is cancelled
ClientRequestToken Idempotent for 10 minutes; changed parameters → IdempotentParameterMismatchException Same token, same result
TransactionCanceledException CancellationReasons in request order (ConditionalCheckFailed, TransactionConflict, ThrottlingError …); SDKs don't retry it
Transaction IAM Per action: dynamodb:PutItem, UpdateItem, DeleteItem, GetItem, ConditionCheckItem; scope with dynamodb:EnclosingOperation
Isolation Serializable with single-item calls; read-committed with Query, Scan, BatchGetItem

PartiQL

Topic Current facts Memory hook
Statements SELECT, INSERT, UPDATE, DELETE on one table or index; no joins SQL look, NoSQL rules
Cost A SELECT whose WHERE doesn't pin the partition key with = or IN is a full table scan
APIs ExecuteStatement, BatchExecuteStatement (25 statements), ExecuteTransaction (100 statements) 25 batch, 100 transaction
Mixing A batch or transaction is all reads or all writes
INSERT Never overwrites: an existing key → DuplicateItemException
IAM actions dynamodb:PartiQLSelect, PartiQLInsert, PartiQLUpdate, PartiQLDelete
Blocking scans Deny dynamodb:PartiQLSelect when dynamodb:FullTableScan is true

DAX and caching choices

Topic Current facts Memory hook
What it is Managed in-memory write-through cache in your VPC, DynamoDB API-compatible through the DAX client Same API, microseconds
Item cache GetItem / BatchGetItem results; updated by writes through DAX; default TTL 5 min
Query cache Query / Scan results; not updated by writes; default TTL 5 min (query-ttl-millis) Query cache goes stale
Consistency Eventual reads are cached; strongly consistent reads and TransactGetItems pass through Strong skips the cache
⚠️ Cluster size Developer Guide: up to 11 nodes = 1 primary + 10 read replicas (⚠️ unverified: the CreateCluster API reference still says 10); production at least 3 nodes in different AZs 1 + 10, at least 3
Scaling Add replicas online for reads; a larger node type needs a new cluster
Network VPC only; security group allows TCP 8111 (dax://) or 9111 (TLS daxs://); Lambda functions must be attached to the VPC
Security The cluster's service role calls DynamoDB; callers need dax:* actions; per-user LeadingKeys is not enforced DAX wears its own badge
Bypassed writes Writes sent straight to DynamoDB leave DAX stale until TTL
DAX vs ElastiCache DAX: DynamoDB reads with no code change. ElastiCache: aggregates, multi-source data, sessions, custom logic

DynamoDB Streams and Lambda

Topic Current facts Memory hook
Retention and order 24 hours; each change exactly once; ordered per item One day, once, in order
View types KEYS_ONLY, NEW_IMAGE, OLD_IMAGE, NEW_AND_OLD_IMAGES; not editable, re-create the stream
Backfill None: only changes after enabling are captured
Lambda event source mapping Polls each shard 4 times per second, invokes synchronously; GetRecords calls not charged
Batch size Default 100, max 10,000; batching window up to 300 s; payload at most 6 MB
Starting position TRIM_HORIZON or LATEST (LATEST can miss events while the mapping is created)
Default on error Retries until the records expire (24 h), blocking the shard Poison record blocks the shard
Error controls MaximumRetryAttempts (0–10,000), MaximumRecordAgeInSeconds (up to 604,800), BisectBatchOnFunctionError, ReportBatchItemFailures
⚠️ On-failure destinations SQS queue, SNS topic or S3 bucket (only S3 receives the batch payload)
ParallelizationFactor 1–10 concurrent batches per shard, order kept per partition key
Filtering FilterCriteria on eventName, Keys, NewImage, OldImage; up to 5 patterns; no numeric matching Filter before you pay
Execution role dynamodb:DescribeStream, GetRecords, GetShardIterator, ListStreams (AWSLambdaDynamoDBExecutionRole)
Readers per shard At most 2 on a single-Region table, 1 on a global table
Kinesis Data Streams for DynamoDB Longer retention, more consumers, Firehose; records may be out of order or duplicated
⚠️ KCL adapter KCL 3.5.x+ with SDK for Java 2.x; KCL 1.x end of support 2026-01-30

Time to Live

Topic Current facts Memory hook
Attribute Number in Unix epoch seconds; other types and formats are ignored Seconds, not strings
⚠️ Timing Deleted typically within a few days after expiry Days, not seconds
Cost No WCU consumed for TTL deletes in the Region where items expire Free cleanup
Expired but present Still returned by reads → filter on the TTL attribute
Stream record REMOVE with userIdentity.type Service and principalId dynamodb.amazonaws.com
Indexes TTL deletes also remove the item's LSI and GSI entries
Old timestamps More than 5 years in the past → not deleted
Enable or disable One UpdateTimeToLive change per table per hour
⚠️ Global tables Replicated TTL deletes cost replicated write units in other Regions; MRSC tables don't support TTL

Security and fine grained access control

Topic Current facts Memory hook
App-user access Cognito identity pool → role with dynamodb:LeadingKeys = ${cognito-identity.amazonaws.com:sub} Your key, your items
dynamodb:LeadingKeys Partition key values of the request; use with ForAllValues:StringEquals
dynamodb:Attributes Allowed attributes; list the keys too; pair with dynamodb:Select = SPECIFIC_ATTRIBUTES
dynamodb:ReturnValues Restrict to NONE, UPDATED_OLD, UPDATED_NEW to hide attributes on writes
Scan in FGAC policies Never grant it: Scan ignores leading keys
⚠️ Resource-based policies Tables, indexes and streams; max 20 KB; cross-account without assuming a role; Block Public Access Policy on the table
Encryption at rest Always on: AWS owned key (default), AWS managed aws/dynamodb, or a customer managed key Always encrypted
Gateway endpoint Free, route-table based, usable only from inside the VPC
⚠️ Interface endpoint PrivateLink (since March 2024), billed, reachable from on-premises and peered VPCs; clients use the endpoint-specific DNS name (no private DNS)
Endpoint restriction aws:SourceVpce or aws:SourceVpc condition in the table or endpoint policy
ABAC Tag conditions aws:ResourceTag, aws:RequestTag, aws:TagKeys; indexes inherit table tags
⚠️ Managed policy AmazonDynamoDBFullAccess deprecated 2025-04-25 → AmazonDynamoDBFullAccess_v2

Serverless patterns and table operations

Topic Current facts Memory hook
Session store DynamoDB + TTL: reachable from every instance, self-expiring, serverless; ElastiCache: lower latency but a cluster to run; S3: too slow and costly per request for tiny objects; EBS or instance store: one instance only Shared, serverless, self-expiring
Random-suffix sharding Best write spread; reads must query all N suffixes and merge Random spreads, reads fan out
Calculated-suffix sharding Suffix from a hash of a known attribute, so one item can be read with GetItem Calculated = findable
Large objects Store in S3, keep bucket/key + metadata in DynamoDB; no transaction spans both Blob in S3, pointer in DynamoDB
Empty a table Delete and recreate it, not Scan + DeleteItem Drop, don't sweep
⚠️ Copy a table Export to S3 (needs PITR, no RCU) + import from S3 into a new table (no WCU); or AWS Backup, Glue, custom code Export, then import
⚠️ PITR Per-second restore within a 1–35 day period (RecoveryPeriodInDays); every restore creates a new table
On-demand backups DynamoDB or AWS Backup; kept until deleted; no performance impact
⚠️ Deletion protection DeletionProtectionEnabled blocks DeleteTable for everyone
Global tables MREC Default; asynchronous (typically within a second), last writer wins, 99.999 % SLA
⚠️ Global tables MRSC Exactly 3 Regions (or 2 + witness), RPO 0, strong reads in any Region; no TTL, LSIs or transactions Three Regions, zero RPO
DynamoDB Local Port 8000, --endpoint-url http://localhost:8000; throughput ignored; JAR, Docker, Maven or CloudShell

Numbers to know

Item Value Note
Item size 400 KB Attribute names included
Partition key / sort key length 2,048 / 1,024 bytes Minimum 1 byte
Per-partition throughput 3,000 RCU / 1,000 WCU Hot-key ceiling
Partition size 10 GB Also the LSI item-collection limit
Read / write unit size 4 KB / 1 KB Round each item up
Eventual / transactional read factor ½ / 2 Relative to a strongly consistent read
Query or Scan page 1 MB Measured before the filter
BatchWriteItem 25 requests, 16 MB Puts and deletes only
BatchGetItem 100 items, 16 MB
Transaction 100 actions, 4 MB ⚠️ older material: 25 items
Idempotency token window 10 minutes ClientRequestToken up to 36 characters
LSIs per table 5 Fixed, defined only at creation
GSIs per table 20 Default quota
Projected non-key attributes 100 Across all indexes of a table
Expression length / operators 4 KB / 300 IN takes up to 100 operands
Nesting depth 32 levels Lists and maps
Number precision 38 digits Sent as strings
Tables per Region 2,500 Up to 10,000 via the account team
Concurrent control-plane operations 500 Then LimitExceededException
⚠️ Switches to on-demand 4 per rolling 24 h Back to provisioned any time
New on-demand table 4,000 writes/s, 12,000 reads/s Then 2× the previous peak instantly
On-demand growth window 30 minutes For traffic beyond 2× the previous peak
On-demand per-table quota 40,000 RRU / 40,000 WRU Adjustable
Provisioned quotas 40,000 per table, 80,000 per account RCU and WCU each, adjustable
Provisioned decreases Up to 27 per day 4 banked + 1 per hour
Burst capacity 300 seconds Of unused provisioned capacity
Auto scaling target 20–90 % Console suggests 70 %
On-demand price (us-east-1) $0.625 / $0.125 per million WRU / RRU, Standard class
Table-class changes 2 per 30 days Standard ↔ Standard-IA
Stream retention 24 hours Kinesis Data Streams for longer
Stream readers per shard 2 (global tables: 1) More readers → throttling
ESM batch size 100 default, 10,000 max Batching window up to 300 s
ESM parallelization factor 1–10 Order kept per partition key
⚠️ DAX nodes 11 = 1 primary + 10 replicas Developer Guide; ⚠️ unverified (API reference: 10); production at least 3
DAX TTL default 5 minutes Item cache and query cache
DAX ports 8111 / 9111 dax:// / TLS daxs://
⚠️ TTL deletion Within a few days Older material: 48 hours
⚠️ PITR period 1–35 days Restores go to a new table
Resource-based policy size 20 KB Tables, indexes, streams
DynamoDB Local port 8000 --endpoint-url http://localhost:8000

Decision rules

Memory hooks