Stelvio provides high-level abstractions for AWS resources, exposing the most commonly used configuration options through component constructors. However, in some cases you might need fine-grained control of certain aspects of the underlying Pulumi resources that Stelvio creates.
The customize parameter allows you to override or extend default Pulumi resource properties without modifying Stelvio's source code.
When to Use Customization
Use the customize parameter when you need to:
Set Pulumi properties not exposed by Stelvio's API (e.g., force_destroy on S3 buckets)
Override default values that Stelvio sets internally
Add tags, encryption settings, or other resource-specific configurations
Configure advanced features like VPC settings or custom IAM policies
Basic Usage
Pass a customize dictionary to any Stelvio component. The dictionary keys correspond to the underlying resources that the component creates:
In this example, "bucket" refers to the S3 bucket resource created by the Bucket component, and force_destroy is a Pulumi property that allows the bucket to be deleted even when it contains objects.
Understanding Resource Keys
Each Stelvio component creates one or more underlying Pulumi resources. The customize dictionary keys match the resource names defined in the component's resources dataclass.
Subscription components (DynamoDB streams, SQS, SNS, S3 events) that create Lambda functions include a nested function key. This key accepts the same customization options as FunctionCustomizationDict, allowing you to customize the subscription's Lambda function.
Subscription Type
Resource Keys
DynamoSubscription
function (nested), event_source_mapping
QueueSubscription
function (nested), event_source_mapping
TopicSubscription
function (nested), permission, topic_subscription
BucketNotifySubscription
function (nested), permission, queue_policy, topic_policy
Example with DynamoDB stream subscription:
fromstelvio.aws.dynamo_dbimportDynamoTabletable=DynamoTable("orders",fields={"id":"string"},partition_key="id",stream="new-and-old-images",)# Subscribe with function customizationtable.subscribe("functions/stream_handler.process",customize={"function":{"function":{"memory_size":512,"timeout":60}},"event_source_mapping":{"batch_size":100,"starting_position":"LATEST",}})
How Customization Works
When you provide customizations, Stelvio merges your values with its default configuration:
Stelvio defaults are applied first
Your customizations override or extend those defaults
This means you only need to specify the properties you want to change—Stelvio's sensible defaults remain in place for everything else.
Shallow Merge
The merge is shallow at each property level. If you customize a nested object (like tags),
your entire object replaces the default, rather than being deep-merged.
For example, if defaults have {"tags": {"a": 1, "b": 2}} and you provide
{"tags": {"c": 3}}, the result is {"tags": {"c": 3}}—not {"tags": {"a": 1, "b": 2, "c": 3}}.
Common Pitfalls
Nested Object Replacement
When customizing nested objects, the entire nested object is replaced, not merged:
# Default tags from Stelvio or global customize:# {"bucket": {"tags": {"Team": "platform", "Cost": "shared"}}}# ❌ This replaces ALL default tags - Team and Cost are lost!bucket=Bucket("my-bucket",customize={"bucket":{"tags":{"Env":"dev"}}})# Result: tags = {"Env": "dev"}# ✅ To keep existing tags, include them in your customization:bucket=Bucket("my-bucket",customize={"bucket":{"tags":{"Team":"platform","Cost":"shared","Env":"dev",# Your addition}}})
Global + Instance Tag Replacement
The same shallow merge applies when combining global and per-instance customization:
@app.configdefconfiguration(env:str)->StelvioAppConfig:returnStelvioAppConfig(customize={Bucket:{"bucket":{"tags":{"Team":"platform","Cost":"shared"}}}})@app.rundefrun()->None:# ❌ Per-instance tags completely replace global tagsbucket=Bucket("my-bucket",customize={"bucket":{"tags":{"Env":"dev"}}})# Result: tags = {"Env": "dev"} - Team and Cost are gone!
Global Customization
Apply customizations to all instances of a component type using the customize option in StelvioAppConfig:
fromstelvio.appimportStelvioAppfromstelvio.configimportStelvioAppConfigfromstelvio.aws.s3importBucketfromstelvio.aws.functionimportFunctionapp=StelvioApp("my-project")@app.configdefconfiguration(env:str)->StelvioAppConfig:returnStelvioAppConfig(customize={Bucket:{"bucket":{"force_destroy":True}},Function:{"function":{"tracing_config":{"mode":"Active"}}}})@app.rundefrun()->None:# Both buckets inherit force_destroy=Truebucket1=Bucket("bucket-one")bucket2=Bucket("bucket-two")# All functions have X-Ray tracing enabledfn=Function("my-fn",handler="functions/handler.main")
The global customize dictionary uses component types as keys (e.g., Bucket, Function) and the same resource customization dictionaries as values.
Combining Global and Per-Instance Customization
When both global and per-instance customizations are provided, they are merged with the following precedence (highest to lowest):
Per-instancecustomize parameter
Globalcustomize from StelvioAppConfig
Stelvio defaults
@app.configdefconfiguration(env:str)->StelvioAppConfig:returnStelvioAppConfig(customize={Bucket:{"bucket":{"force_destroy":True}}})@app.rundefrun()->None:# Uses global customization: force_destroy=Truebucket1=Bucket("bucket-one")# Per-instance overrides global: force_destroy=Falsebucket2=Bucket("bucket-two",customize={"bucket":{"force_destroy":False}})
Environment-Specific Customization
Combine customization with environment-based configuration for environment-specific settings:
If you're using an IDE with Python type checking, the customization dictionaries are fully typed. Your IDE can provide autocompletion and validation for available properties.
Some Stelvio components create sub-components rather than Pulumi resources directly. For these, the customization structure mirrors what you'd use when instantiating the sub-component on its own. These cases are marked (nested) in the table above.
Notification Config Blocks
Keys marked with * (function, queue, topic in Bucket) are notification configuration blocks within the bucket_notification resource, not standalone Pulumi resources. They customize the notification settings for Lambda, SQS, and SNS targets respectively.