DynamoDB features and quotas
This page is the reference for the parts of DynamoDB that shape a table design: how indexes behave, what the API operations cost and limit, and the quotas that a design has to fit inside. Concepts are introduced on the DynamoDB overview.
Keys and items
Section titled “Keys and items”- Partition key (hash key) — required on every item. On a table with no sort key it must be unique.
- Sort key (range key) — optional. With a partition key it forms a composite key, and items sharing a partition key are stored in sort key order.
- Item size — maximum 400 KB, including attribute names and values.
Secondary indexes
Section titled “Secondary indexes”Local secondary index (LSI)
- Must be created when the table is created and cannot be added later.
- Same partition key as the base table, different sort key.
- Up to 5 per table.
- Shares the table’s provisioned throughput.
Global secondary index (GSI)
- Can be created and deleted at any time.
- Different partition key and/or sort key from the base table.
- Up to 20 per table by default.
- Has its own throughput settings, independent of the table.
Projections
Section titled “Projections”An index stores only the attributes you project into it. The choice is a direct trade-off between index size, write cost and how often a query has to fetch the rest of the item from the base table.
| If a query needs | Project | Cost | Effect |
|---|---|---|---|
| A few attributes, as fast as possible | Just those attributes | Minimal | Lowest latency for non-key access |
| Some non-key attributes frequently | Those attributes | Moderate | Avoids the cost of table scans |
| Most non-key attributes | Those attributes, or the whole item | Up to double the storage and write cost | Maximum query flexibility |
| Rarely queried, frequently written | Keys only | Minimal | Cheapest writes for non-key items |
Up to 100 user-specified projected attributes may be defined across all of a table’s
local and global secondary indexes combined. Projecting the same attribute name into two
indexes counts twice. The quota does not apply to indexes with a projection type of
KEYS_ONLY or ALL.
Sparse indexes
Section titled “Sparse indexes”An index entry only exists for items that actually carry the indexed attribute. If a
Status attribute is written only on open orders, an index on Status contains only
open orders — a small index that answers “list the open orders” without scanning the
table, and that shrinks by itself as orders close. Sparse indexes are one of the
cheapest ways to serve a selective query.
Using a GSI as a read replica
Section titled “Using a GSI as a read replica”Because a GSI has independent throughput, projecting the whole item into an index with the same key schema as the table gives a second, separately provisioned copy of the data. That is useful for separating classes of traffic — analytics reads off the index while writes land on the table, or high-throughput customers on the table and lower tiers on the index. The copy is eventually consistent with the table, so it is not a substitute for a strongly consistent read.
Data types
Section titled “Data types”- Scalar — number, string, binary, boolean, null.
- Document — list, map.
- Set — number set, string set, binary set.
Time to live (TTL)
Section titled “Time to live (TTL)”- Deletes items automatically after an expiry timestamp held in a nominated attribute.
- The attribute must be a number holding a Unix epoch time in seconds; one TTL attribute per table.
- Useful for session data, staging data and logs.
- TTL deletions are free and do not consume write capacity in the Region where they occur, though replicated deletions in a global table do.
- TTL deletions appear in DynamoDB Streams.
- TTL is not available on global tables configured for multi-Region strong consistency.
Query and scan
Section titled “Query and scan”Query requires a partition key value and optionally a sort key condition. It reads
only the matching partition, can run against any LSI or GSI, can return results in
ascending or descending sort key order, and pages through results with a Limit
parameter.
Scan examines every item in the table, applies any filter expression after reading, and therefore consumes capacity proportional to the table rather than to the result. It supports parallel segments for throughput. Prefer a query, or an index that turns the scan into a query.
Both cap a single response at 1 MB, after which the caller must page.
Batch and transactional operations
Section titled “Batch and transactional operations”| Operation | Limit |
|---|---|
BatchGetItem | Up to 100 items, 16 MB per request |
BatchWriteItem | Up to 25 put or delete requests, 16 MB per request |
TransactWriteItems | Up to 100 write actions against up to 100 distinct items, 4 MB aggregate |
TransactGetItems | Up to 100 get actions against up to 100 distinct items, 4 MB aggregate |
Batch operations may partially succeed and return unprocessed items for the caller to
retry. Transactions are all-or-nothing. Note the difference between the two 25s and
100s above: BatchWriteItem is capped at 25 requests, transactions at 100 actions.
Error handling
Section titled “Error handling”ProvisionedThroughputExceededException— the request exceeded provisioned capacity.ThrottlingException— too many control-plane operations.ResourceNotFoundException— the table or index does not exist.TransactionCanceledException— a transaction failed; the exception lists a cancellation reason per item.
Retry with exponential backoff and jitter. The AWS SDKs do this by default for throttling errors.
Metrics worth alarming on
Section titled “Metrics worth alarming on”ConsumedReadCapacityUnits, ConsumedWriteCapacityUnits, ReadThrottleEvents,
WriteThrottleEvents, ThrottledRequests, SystemErrors, and — on eventually
consistent global tables — ReplicationLatency.
Quotas
Section titled “Quotas”| Quota | Default |
|---|---|
| Item size | 400 KB |
| Items per table, table size | No limit |
| Tables per account per Region | 2,500 (raisable to 10,000) |
| Partition key length | 2,048 bytes |
| Sort key length | 1,024 bytes |
| Attribute name length | 64 KB |
| Attributes per item | No fixed limit, subject to the 400 KB item size |
| Table-level throughput | 40,000 read units and 40,000 write units, on-demand or provisioned |
| Account-level provisioned throughput | 80,000 read and 80,000 write capacity units per Region |
| Per-partition throughput | 3,000 read units, 1,000 write units |
| Global secondary indexes per table | 20 |
| Local secondary indexes per table | 5 |
| Projected attributes across all indexes | 100 user-specified |
| Query and scan response size | 1 MB |
| Point-in-time recovery window | 35 days |
| Streams retention | 24 hours |
Most of these are adjustable through Service Quotas; the item size, key lengths, page size and per-partition throughput are not.
Design practices
Section titled “Design practices”- Choose a partition key with enough distinct values to spread load evenly.
- Model to the queries the application actually makes; DynamoDB rewards a schema designed backwards from its access patterns.
- Use sparse indexes to keep selective queries cheap.
- Project the minimum set of attributes an index needs.
- Retry with exponential backoff.
- Batch where the semantics allow it, and reserve transactions for cases that genuinely need atomicity.
- Compress or offload large attribute values — put the blob in S3 and the pointer in the item.