AWS serverless NoSQL database with single-digit millisecond latency at any scale, ideal for applications requiring high performance and automatic scalability.
DynamoDB is AWS's serverless NoSQL database that offers consistent single-digit millisecond latency regardless of data size or request volume. No servers to manage, patches to apply, or capacity to manually plan.
Unlike relational databases, DynamoDB uses a flexible data model where each item can have different attributes. Its distributed architecture automatically partitions data using the partition key, ensuring horizontal scalability without theoretical limits.
DynamoDB's design prioritizes availability and latency over strong consistency, following the CAP theorem. This means applications must be designed considering eventual consistency, though it offers strong consistency as an option for specific reads.
DynamoDB uses a data model based on tables, items, and attributes:
Consider an e-commerce system with orders and customers:
# Item structure in a single table
{
"PK": "CUSTOMER#123",
"SK": "PROFILE",
"name": "Juan Pérez",
"email": "juan@example.com",
"created": "2024-01-15"
}
{
"PK": "CUSTOMER#123",
"SK": "ORDER#456",
"total": 99.99,
"status": "shipped",
"items": ["product-a", "product-b"]
}
{
"PK": "ORDER#456",
"SK": "METADATA",
"customer_id": "123",
"shipping_address": "...",
"payment_method": "card"
}This pattern enables efficient queries:
PK = CUSTOMER#123 AND SK = PROFILEPK = CUSTOMER#123 AND SK begins_with ORDER#PK = ORDER#456 AND SK = METADATAEnables queries by attributes different from the primary key. Each GSI has its own partition key and sort key, with independent throughput capacity.
When to use GSI:
Shares the same partition key as the base table but uses a different sort key. Limited to 10GB per partition.
When to use LSI:
DynamoDB Streams captures real-time changes (INSERT, MODIFY, DELETE) and sends them to AWS Lambda or Kinesis. Each stream record contains:
{
"eventName": "INSERT",
"dynamodb": {
"Keys": {"PK": {"S": "ORDER#456"}},
"NewImage": {"status": {"S": "created"}, "total": {"N": "99.99"}},
"StreamViewType": "NEW_AND_OLD_IMAGES"
}
}Common patterns:
import boto3
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('ecommerce')
# Query with filter
response = table.query(
KeyConditionExpression=Key('PK').eq('CUSTOMER#123'),
FilterExpression=Attr('status').eq('active'),
Limit=10
)
# Pagination
while 'LastEvaluatedKey' in response:
response = table.query(
KeyConditionExpression=Key('PK').eq('CUSTOMER#123'),
ExclusiveStartKey=response['LastEvaluatedKey'],
Limit=10
)Time to Live (TTL): automatically expires items using a Unix timestamp.
# Configure TTL on an attribute
table.meta.client.update_time_to_live(
TableName='sessions',
TimeToLiveSpecification={
'AttributeName': 'expires_at',
'Enabled': True
}
)Backup strategies:
| Workload | On-demand | Provisioned | Recommendation |
|---|---|---|---|
| Development/Testing | $0.25 per 1M reads | $0.09 per RCU/month | On-demand |
| Predictable traffic (1000 RPS constant) | $648/month | $233/month | Provisioned |
| Sporadic traffic (5000 RPS spikes) | $324/month | $1,166/month | On-demand |
| New application (unknown pattern) | Variable | Throttling risk | On-demand |
Key factors:
resource "aws_dynamodb_table" "ecommerce" {
name = "ecommerce"
billing_mode = "PAY_PER_REQUEST"
hash_key = "PK"
range_key = "SK"
attribute {
name = "PK"
type = "S"
}
attribute {
name = "SK"
type = "S"
}
attribute {
name = "GSI1PK"
type = "S"
}
global_secondary_index {
name = "GSI1"
hash_key = "GSI1PK"
projection_type = "ALL"
}
stream_enabled = true
stream_view_type = "NEW_AND_OLD_IMAGES"
point_in_time_recovery {
enabled = true
}
tags = {
Environment = "production"
Service = "ecommerce"
}
}DynamoDB represents a fundamental shift in database design for serverless applications. Its per-request pricing model eliminates the need to provision capacity, but requires careful schema design based on specific access patterns.
For teams migrating from relational databases, DynamoDB demands rethinking normalization — single-table design may seem counterintuitive, but it's essential for minimizing costs and latency. The absence of JOINs means denormalization and data duplication are valid strategies.
Event-driven architecture ecosystems benefit enormously from DynamoDB Streams, enabling reactive architectures that scale automatically without infrastructure management.
Cloud computing model where the provider manages infrastructure automatically, allowing code execution without provisioning or managing servers, paying only for actual usage.
AWS serverless compute service that runs code in response to events without provisioning or managing servers, automatically scaling from zero to thousands of concurrent executions.
Architectural pattern where components communicate through asynchronous events, enabling decoupled, scalable, and reactive systems.
Architecture design for scaling a personal second brain to a production system with AWS serverless — from the current prototype to specialized use cases in legal, research, and community building.
Collection of 13 Terraform modules published on the Terraform Registry for deploying serverless architectures on AWS, with 12 examples covering basic ECS to full-stack CRUD with DynamoDB and AgentCore with MCP.
Production-ready serverless backend for a personal knowledge graph — DynamoDB, Lambda, Bedrock, MCP, Step Functions. The implementation of the architecture described in the 'From Prototype to Production' essay.