DynamoDB: Items, Expressions, GSI and Transactions Reference Guide
By DevShelfHub
Item API, expressions, GSI vs LSI, PartiQL, transactions, streams, Lambda triggers, DAX, TTL, and backups — the complete DynamoDB reference for boto3 1.34+ and AWS CLI v2. Covers the Resource and Client APIs, key design patterns, and local development with dynamodb-local.
94 items
◷ 9 min
Key-value
GSI
PartiQL
Start hereQuick start · 6 you’ll reach for daily
Create tableaws dynamodb create-table ...
Put itemtable.put_item(Item={...})
Get itemtable.get_item(Key={...})
Query by PKKey('pk').eq(...) & Key('sk').begins_with(...)
DynamoDB is fully managed — the API is the version. Recent flagship additions: PartiQL
(SQL-style queries), transactional writes, on-demand backups + PITR, DynamoDB Streams → Kinesis,
and the boto3 Resource API (the type-friendly wrapper that handles Decimal coercion for you).
Always prefer the Resource API in Python unless you need a feature the Client exposes first.
CLI · local · boto3Setup
bash
# AWS CLI (already-installed env)
aws --version
aws configure # access key / secret / region
# Local-only dev — no AWS account needed
docker run -d --name ddb \
-p 8000:8000 \
amazon/dynamodb-local:latest \
-jar DynamoDBLocal.jar -sharedDb
# Point the CLI at the local endpoint
aws dynamodb list-tables --endpoint-url http://localhost:8000
# Python SDK
pip install "boto3>=1.34"
python - <<'PY'
import boto3
ddb = boto3.resource("dynamodb", endpoint_url="http://localhost:8000",
region_name="us-east-1")
print([t.name for t in ddb.tables.all()])
PY
# Browse / model visually with NoSQL Workbench (separate desktop tool)
# https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.html
Bulk export — feed analytics without touching live RCU.
Full pipeline · ~30 linesEnd-to-end · Order tracking
Single table with CUSTOMER#<id> partition key and
ORDER#<ts> sort key. Three operations: place an order (insert-only),
mark it paid (conditional update), list all orders for a customer (Query on pk).
Single-table design is the idiomatic shape.
Overload pk / sk with prefixes
(CUSTOMER#, ORDER#, PROD#)
so one Query reaches everything related to an entity. Stop the moment you reach for a join.
Sparse GSI for status filters.
Only set the GSI key attribute on items you actually want to find — the index then shrinks to
just those rows. Cheap, fast, and grows with the relevant subset, not the whole table.
Use ConditionExpression instead of read-then-write.
Atomic check + write in one round-trip means no race window. attribute_not_exists(pk)
is the right way to do “create only if new”.
Common trapsWatch out for
FilterExpression doesn’t save money.
You still pay RCU for every row matched by the key condition; the filter just hides
them after the read. If you’re filtering big result sets, you need a GSI.
Don’t store float from Python.
Boto3’s Resource API refuses float on write to prevent precision loss.
Always pass Decimal for N attributes.
Hot partitions kill throughput.
One partition = one physical node serving up to a few thousand WCU. If your pk pattern
concentrates traffic (e.g. pk = "today"), you’ll throttle even though
the table has plenty of overall capacity. Spread with a suffix or a hash bucket.
DynamoDB is a fully managed serverless key-value and document database from AWS. It scales to any traffic level with single-digit millisecond latency. Use it for user sessions, event logs, shopping carts, and any workload with a clear primary key access pattern and variable traffic.
How do I choose a good partition key in DynamoDB?
Choose a partition key with high cardinality that distributes traffic evenly across partitions. Avoid keys like status or date that concentrate writes on a single partition (hot-spotting). Good candidates are userId, orderId, or a composite like tenantId#entityId.
What is the difference between a GSI and an LSI in DynamoDB?
A Local Secondary Index (LSI) shares the same partition key as the base table but has a different sort key — it must be created at table creation time. A Global Secondary Index (GSI) can have any partition and sort key and can be added or removed at any time. GSIs are more flexible; LSIs are tighter and cheaper to query.
How do DynamoDB transactions work?
DynamoDB transactions group up to 100 item-level operations across one or more tables into an atomic all-or-nothing unit. Use transact_write_items for writes (Put, Update, Delete, ConditionCheck) and transact_get_items for reads. Transactions cost 2x the normal read/write capacity.
How do I query DynamoDB without scanning the whole table?
Always query using the primary key or a GSI key with table.query(KeyConditionExpression=Key("pk").eq(...)). Scans read every item and are expensive. If you find yourself scanning frequently, redesign the data model to support your access patterns with a GSI.
Does DynamoDB support SQL-style queries?
Yes, via PartiQL — a SQL-compatible query language that lets you use SELECT, INSERT, UPDATE, and DELETE syntax against DynamoDB. It is available in the console, CLI (execute-statement), and boto3 (client.execute_statement). PartiQL is convenient but still translates to the same key-based operations underneath.