This guide explains how to create and manage DynamoDB tables with Stelvio. You can create tables with partition keys, sort keys, and secondary indexes for efficient querying.
Creating a DynamoDB table
Creating a DynamoDB table in Stelvio is straightforward. Define fields used as keys or indexes with either friendly field type names or the enum:
fromstelvio.aws.dynamo_dbimportDynamoTable,FieldType# Using friendly field type stringsorders_table=DynamoTable(name="orders",fields={"customer_id":"string","order_date":"string","status":"string","total":"number",},partition_key="customer_id",sort_key="order_date")# Or using the FieldType enumorders_table=DynamoTable(name="orders",fields={"customer_id":FieldType.STRING,"order_date":FieldType.STRING,"status":FieldType.STRING,"total":FieldType.NUMBER,},partition_key="customer_id",sort_key="order_date")
Field Types
Stelvio supports both friendly string names and enum values for field types:
Friendly String
Enum
DynamoDB Type
Use For
"string"
FieldType.STRING
S
Text data, IDs
"number"
FieldType.NUMBER
N
Numeric data
"binary"
FieldType.BINARY
B
Binary data
You can also use the DynamoDB type directly ("S", "N", "B") if you prefer.
Secondary Indexes
DynamoDB supports two types of secondary indexes to improve query performance. You can add them when creating your table:
You can control which attributes are copied to your indexes using projections:
# Keys only (default)LocalIndex(sort_key="status")# All attributes LocalIndex(sort_key="status",projections="all")# Specific attributesLocalIndex(sort_key="status",projections=["total","customer_id"])
Choosing Projections
Use "keys-only" when you only need to retrieve keys for further queries
Use specific attributes when you know exactly which fields your queries need
Use "all" when you need to retrieve complete items from index queries (costs more storage)
Index Types
Local Secondary Index (LSI): Same partition key as your table, different sort key. Queries within the same partition.
Global Secondary Index (GSI): Different partition key (and optionally sort key). Queries across the entire table.
Index Limitations
Local indexes can only be created when you create the table - you cannot add or remove them later
Global indexes can be added or removed from existing tables, but this is a background operation that takes time
Each table can have up to 5 local indexes and 20 global indexes
DynamoDB Streams
DynamoDB Streams capture changes to your table data in real-time. Enable streams to react to creates, updates, and deletes:
fromstelvio.aws.dynamo_dbimportDynamoTable,StreamView# Enable streams with string literalsorders_table=DynamoTable(name="orders",fields={"customer_id":"string","order_date":"string",},partition_key="customer_id",sort_key="order_date",stream="new-and-old-images"# Capture before and after data)# Or use the StreamView enumorders_table=DynamoTable(name="orders",fields={"customer_id":"string","order_date":"string",},partition_key="customer_id",sort_key="order_date",stream=StreamView.NEW_AND_OLD_IMAGES)
Stream View Types
Choose what data to capture when items change:
View Type
String Literal
What's Captured
Keys Only
"keys-only"
Only the key attributes of changed items
New Image
"new-image"
The entire item after modification
Old Image
"old-image"
The entire item before modification
New and Old Images
"new-and-old-images"
Both before and after images
Choosing Stream Types
Keys Only: Minimal data, useful when you just need to know what changed
New Image: Great for replication or downstream processing of current state
Old Image: Useful for audit trails or rollback scenarios
New and Old Images: Complete change tracking, but uses more bandwidth
Accessing Stream Properties
Once streams are enabled, you can access the stream ARN programmatically:
# Access stream ARN for other resourcesstream_arn=orders_table.stream_arn# Output[str] | None
Stream Retention
DynamoDB streams retain data for 24 hours only. This is a fixed AWS service limit that cannot be changed. After 24 hours, stream records are automatically deleted. Plan your stream processing accordingly.
Stream Subscriptions
Process stream changes in real-time by subscribing Lambda functions to your DynamoDB streams:
# Create table with streams enabledorders_table=DynamoTable(name="orders",fields={"customer_id":"string","order_date":"string"},partition_key="customer_id",sort_key="order_date",stream="new-and-old-images")# Subscribe functions to stream changesorders_table.subscribe("process-orders","functions/orders.process_changes")orders_table.subscribe("update-inventory","functions/inventory.update_stock")
Lambda Configuration
For custom Lambda settings, you can pass options directly:
# Direct optionsorders_table.subscribe("custom-handler","functions/orders.handler",timeout=60,memory=512)# With FunctionConfigfromstelvio.aws.functionimportFunctionConfigorders_table.subscribe("config-handler",FunctionConfig(handler="functions/orders.handler",timeout=60,memory=512))# With dictionaryorders_table.subscribe("dict-handler",{"handler":"functions/orders.handler","timeout":30,"memory":256})
Stream Configuration
Control EventSourceMapping behavior with stream-specific parameters:
# With filters and custom batch sizeorders_table.subscribe("filtered-handler","functions/orders.handler",filters=[{"pattern":'{"eventName":["INSERT","MODIFY"]}'}],batch_size=50)# With batch size onlyorders_table.subscribe("batch-handler","functions/orders.handler",batch_size=25)# Combine with Lambda configurationorders_table.subscribe("complex-handler","functions/orders.handler",filters=[{"pattern":'{"dynamodb":{"NewImage":{"status":{"S":["active"]}}}}'}],batch_size=50,memory=512,timeout=60)
Stream Configuration Options:
filters: AWS EventSourceMapping filter criteria to process only matching records
batch_size: Number of records to send to Lambda in each batch (default: 100)
Filter Examples
Field values: '{"dynamodb":{"NewImage":{"status":{"S":["active"]}}}}'
Stream subscriptions only give Lambda permission to read stream data. If your Lambda function needs to query, scan, or modify the table itself, you must link the table to the function separately.
Linking to Lambda Functions
When you link a DynamoDB table to a Lambda function, Stelvio automatically configures the necessary IAM permissions:
fromstelvio.aws.dynamo_dbimportDynamoTablefromstelvio.aws.functionimportFunction# Create tableusers_table=DynamoTable(name="users",fields={"user_id":"string","name":"string"},partition_key="user_id")# Create function with automatic table accessprocess_user=Function(name="process-user",handler="functions/users.handler",links=[users_table]# Automatically gets table + index permissions)
Index operations: Query, Scan (read-only access to all indexes)
Index Permissions
DynamoDB indexes only support Query and Scan operations. Write operations (PutItem, UpdateItem, DeleteItem) are only performed on the main table, with DynamoDB automatically maintaining the indexes.
Customization
The DynamoTable component supports the customize parameter to override underlying Pulumi resource properties. For an overview of how customization works, see the Customization guide.