At scale the bill is driven by item size and request patterns, and design choices can change it by an order of magnitude.
Item size multiplies cost: every write is billed per 1 KB and every read per 4 KB. Patterns that keep items lean:
- put large blobs (documents, images) in S3 and store only the object key
- vertical partitioning: split a big entity into several items under one partition key (
SK = PROFILE,SK = SETTINGS,SK = HISTORY#...) so frequent updates touch small items - compress large text attributes (gzip into a binary attribute) when you must keep them inline
- keep attribute names short in huge tables; names count toward item size
The hard limit is 400 KB per item, including attribute names.
DAX (DynamoDB Accelerator) is an in-memory, write-through cache cluster with a DynamoDB-compatible API, giving microsecond reads for read-heavy, repetitive access. It serves eventually consistent reads only and adds a cluster to run; for many apps an application-level cache or simply reading less is enough.
Other levers: use eventually consistent reads where possible (half price), project only needed attributes into GSIs, delete unused GSIs, use the Standard-IA table class for rarely accessed data (cheaper storage, pricier requests), switch steady workloads to provisioned capacity with auto scaling or reserved capacity, and watch ConsumedReadCapacityUnits per operation using ReturnConsumedCapacity.
Example
import gzip
import boto3
table = boto3.resource("dynamodb").Table("App")
doc = ("lorem ipsum " * 4000).encode() # ~48 KB of text
table.put_item(Item={"PK": "DOC#1", "SK": "BODY",
"body_gz": gzip.compress(doc)}) # binary attribute
r = table.put_item(Item={"PK": "DOC#1", "SK": "META", "title": "Notes", "views": 0},
ReturnConsumedCapacity="TOTAL")
print(r["ConsumedCapacity"]["CapacityUnits"]) # 1.0 small item, cheap updates
body = gzip.decompress(table.get_item(
Key={"PK": "DOC#1", "SK": "BODY"})["Item"]["body_gz"].value)
print(len(body) // 1000, "KB raw,", len(gzip.compress(doc)), "bytes stored")
# 48 KB raw, 142 bytes stored (repetitive text compresses well)Remember
- Item size drives cost: writes per 1 KB, reads per 4 KB; max item 400 KB
- Store blobs in S3 and split big entities into several items
- DAX caches eventually consistent reads in microseconds
- Eventual reads, lean GSI projections and table classes cut cost
Watch out for
- Incrementing a view counter inside a 300 KB item, paying 300 write units per click.