Lifecycle
Alchemy manages infrastructure through a well-defined lifecycle that handles creation, updates, and deletion of resources. Understanding this lifecycle is essential for building reliable infrastructure.Deployment Phases
Alchemy applications operate in one of three phases:Up Phase (Default)
The up phase creates and updates resources:The up phase is the default. You typically don’t need to specify it explicitly.
Destroy Phase
The destroy phase deletes all resources:Read Phase
The read phase retrieves resource state without making changes:Resource Lifecycle Phases
Individual resources go through their own lifecycle phases:Create Phase
When a resource doesn’t exist in state:1
Handler invoked
Resource handler called with phase “create”
2
Infrastructure provisioned
API calls create the actual infrastructure
3
State saved
Return value is saved to state with status “created”
Update Phase
When resource exists but props have changed:1
Props comparison
Alchemy detects props have changed from state
2
Handler invoked
Resource handler called with phase “update”
3
Infrastructure updated
API calls update the existing infrastructure
4
State updated
New state saved with old props preserved in
oldPropsDelete Phase
When resource is removed from code or explicitly destroyed:1
Orphan detection OR explicit destroy
Resource exists in state but not in code, or app in destroy phase
2
Handler invoked
Resource handler called with phase “delete”
3
Infrastructure deleted
API calls remove the infrastructure
4
State removed
this.destroy() deletes the state fileLifecycle Transitions
First Deployment
Second Deployment (No Changes)
If props haven’t changed, Alchemy skips the update unless
--force is used.Third Deployment (Props Changed)
Fourth Deployment (Resource Removed)
Resource Replacement
Some changes require replacing a resource entirely:1
Detect immutable change
this.replace() is called during update phase2
Mark for replacement
Old resource is added to pending deletions
3
Create new resource
Handler is called again in “create” phase with
isReplacement: true4
Delete old resource
After new resource succeeds, old resource is destroyed
5
Update state
State points to new resource
Finalization
The finalization process runs after all resources are created:1
Execute deferred operations
Operations registered with
scope.defer() run2
Finalize child scopes
Recursively finalize nested scopes
3
Detect orphaned resources
Compare state with resources created in code
4
Destroy pending deletions
Delete resources marked for replacement
5
Destroy orphans
Delete resources no longer in code
6
Run cleanup handlers
Execute functions registered with
scope.onCleanup()Deferred Operations
Defer operations until finalization:Cleanup Handlers
Register cleanup for process exit:Destroy Strategies
Control how resources are destroyed:Sequential (Default)
Destroy resources one at a time:Parallel
Destroy all resources concurrently:Per-Resource Strategy
Override strategy for specific resources:Sequential is safer but slower. Parallel is faster but may cause issues if resources have dependencies.
Force Mode
Force updates even when props haven’t changed:- Recover from state corruption
- Apply provider-side changes
- Debug update logic
Adoption
Adopt existing resources:Error Handling
Handling errors during lifecycle:Best Practices
1
Handle all phases
Implement create, update, and delete logic completely
2
Validate immutability
Call
this.replace() when immutable properties change3
Graceful deletion
Handle 404 errors during deletion (resource already gone)
4
Always finalize
Call
await app.finalize() to clean up orphans5
Use deferred operations
Defer post-deployment tasks until all resources exist
6
Register cleanups
Use
scope.onCleanup() for process exit handlersNext Steps
Resources
Implement resources with proper lifecycle handling
State Management
Understand how state drives the lifecycle
Scopes
Manage scope-level lifecycle and finalization
Deployment
Deploy infrastructure using lifecycle phases