โก Deep Dive into DynamoDB: Design, Modeling, and Best Practices
Amazon DynamoDB is a fully managed NoSQL key-value and document database that delivers single-digit millisecond performance at any scale. It is serverless, supports automatic scaling, built-in security, and multi-region replication.
๐ง Core Concepts
๐น Tables, Items, and Attributes
- Table: Collection of data
- Item: Single row of data (like a document)
- Attribute: Field within an item (like a column)
// Sample item in DynamoDB (JSON format)
{
"UserId": "user-123",
"Name": "Alice",
"Age": 30,
"Email": "alice@example.com"
}
๐น Primary Key
Every item must have a primary key, which can be:
- Partition key only (simple key)
- Partition key + Sort key (composite key)
The partition key determines the data distribution across storage partitions.
// Example composite key
Partition Key: "UserId" = "user-123"
Sort Key: "OrderDate" = "2024-10-10"
๐น Secondary Indexes
- Global Secondary Index (GSI): Query using non-primary key attributes
- Local Secondary Index (LSI): Adds sort key to the existing partition key
Indexes must be defined at table creation (LSI) or can be added later (GSI).
๐น Read and Write Capacity Modes
- On-Demand: Auto-scales based on usage (pay per request)
- Provisioned: Manually set read/write units (cheaper with predictable load)
// Provisioned example
Read Capacity Units (RCU) = 5
Write Capacity Units (WCU) = 10
Use DAX (DynamoDB Accelerator) to cache reads and improve performance.
๐ Data Modeling in DynamoDB
DynamoDB is not relational โ it's designed for access patterns.
โ Design Principles
- One table per application (single-table design)
- Predefine your query patterns
- Use compound keys and GSIs to shape access
- Store denormalized or nested data when appropriate
// Example item with embedded data
{
"UserId": "user-123",
"Type": "Profile",
"Profile": {
"Name": "Alice",
"Email": "alice@example.com"
}
}
โ ๏ธ Avoid joins. You query based on access patterns, not relations.
๐งช Querying & Scanning
๐ Query
Efficient โ uses partition key and optional sort key conditions.
aws dynamodb query \
--table-name Users \
--key-condition-expression "UserId = :uid" \
--expression-attribute-values '{":uid":{"S":"user-123"}}'
๐ Scan
Inefficient โ reads all items. Use only for small datasets or batch jobs.
๐ Security & Access Control
- IAM policies: Grant fine-grained access control
- Encryption at rest: AWS KMS integrated
- Encryption in transit: Enabled by default
- VPC endpoints: Secure internal traffic
// IAM example: Allow read-only access
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:Query",
"dynamodb:Scan"
],
"Resource": "arn:aws:dynamodb:region:acct-id:table/Users"
}
โป๏ธ Streams and Triggers
Enable DynamoDB Streams to capture item changes (insert, update, delete).
- Stream events can trigger AWS Lambda
- Used for audit logging, replication, and downstream processing
// Event structure (example)
{
"eventName": "INSERT",
"dynamodb": {
"Keys": { "UserId": { "S": "user-123" } },
"NewImage": { "Name": { "S": "Alice" } }
}
}
๐ฆ Best Practices
Practice | Reason |
---|---|
Design access patterns first | Helps with schema design in NoSQL |
Prefer Query over Scan |
Better performance and cost |
Avoid hot partitions | Use high-cardinality partition keys |
Use DAX for heavy-read workloads | In-memory caching layer |
Use TTL | Automatically delete expired data |
Monitor with CloudWatch | Track latency, throttles, WCU/RCU usage |
๐ฅ When to Use DynamoDB
- Applications with predictable access patterns
- Serverless apps using AWS Lambda
- Workloads needing massive scale with low latency
- Use cases: IoT, gaming, real-time analytics, chat apps
๐ When Not to Use
- Complex relational joins or multi-table transactions
- Heavy ad-hoc queries
- High write throughput without thoughtful partitioning
๐ Resources
<< back to Guides