Skip to main content
Pulumi logo Pulumi logo
  1. Docs
  2. Infrastructure as Code
  3. Concepts
  4. Resources
  5. Resource options
  6. stateMigrations

Resource option: stateMigrations

    The stateMigrations resource option lets a component author supply an ordered list of callbacks that translate the component’s prior state and the state of its children before diffing. Use it when a new component version changes its internal resource structure while preserving existing cloud resources.

    Applies to custom and component resources. The stateMigrations resource option applies to both custom resources and component resources. It is defined on the base resource-options type in every Pulumi SDK.

    This API is experimental and may change.

    Callback API

    Each migration callback is a pure function that transforms the saved state of a component and its children into the state expected by a new component version.

    Each callback receives the registering component’s URN and the prior state of the component and its descendants. It returns a complete replacement state and, when removing or renaming resource URNs, a mapping from each old URN to its successor. Returning no result leaves the state unchanged and allows later callbacks to run.

    The prior subtree contains the component itself first and then its descendants in checkpoint resource format. The registering URN can differ from the root’s prior URN when Pulumi matches it through an alias. Each callback receives the preceding callback’s result.

    A changed result must contain the entire replacement subtree, including unchanged resources. Every input URN must either remain in the result or have a successor mapping to a resource in the result, but not both. Multiple removed URNs can map to the same successor.

    Example

    Define a migration callback and pass it to a component through the stateMigrations option.

    import * as pulumi from "@pulumi/pulumi";
    
    // Shape of pulumi.StateMigrationArgs, shown here for reference.
    type StateMigrationArgs = {
        urn: pulumi.URN;
        oldState: Record<string, any>[];
    };
    
    // Shape of pulumi.StateMigrationResult, shown here for reference.
    type StateMigrationResult = {
        newState: Record<string, any>[];
        successors?: Record<pulumi.URN, pulumi.URN>;
    };
    
    function migrate(args: pulumi.StateMigrationArgs): pulumi.StateMigrationResult | undefined {
        // args.urn identifies the component being registered.
        // args.oldState contains the component's prior state and its descendants.
        // Return { newState, successors } when the state needs migration.
        return undefined;
    }
    
    const component = new MyComponent("example", {}, {
        stateMigrations: [migrate],
    });
    

    API reference: StateMigrationArgs · StateMigrationResult.

    from typing import Any
    
    import pulumi
    
    
    # Fields of pulumi.StateMigrationArgs, shown here for reference.
    class StateMigrationArgs:
        urn: str
        old_state: list[dict[str, Any]]
    
    
    # Fields of pulumi.StateMigrationResult, shown here for reference.
    class StateMigrationResult:
        new_state: list[dict[str, Any]]
        successors: dict[str, str] | None
    
    
    def migrate(args: pulumi.StateMigrationArgs) -> pulumi.StateMigrationResult | None:
        # args.urn identifies the component being registered.
        # args.old_state contains the component's prior state and its descendants.
        # Return pulumi.StateMigrationResult(new_state=..., successors=...) when needed.
        return None
    
    
    component = MyComponent(
        "example",
        opts=pulumi.ResourceOptions(state_migrations=[migrate]),
    )
    

    API reference: StateMigrationArgs · StateMigrationResult.

    // Shape of pulumi.StateMigrationArgs, shown here for reference.
    type StateMigrationArgs struct {
        URN      pulumi.URN
        OldState []map[string]any
    }
    
    // Shape of pulumi.StateMigrationResult, shown here for reference.
    type StateMigrationResult struct {
        NewState   []map[string]any
        Successors map[string]string
    }
    
    migrate := func(_ context.Context, args *pulumi.StateMigrationArgs) (*pulumi.StateMigrationResult, error) {
        // args.URN identifies the component being registered.
        // args.OldState contains the component's prior state and its descendants.
        // Return &pulumi.StateMigrationResult{NewState: ..., Successors: ...}, nil when needed.
        return nil, nil
    }
    
    component, err := NewMyComponent(ctx, "example",
        pulumi.StateMigrations([]pulumi.StateMigration{migrate}),
    )
    if err != nil {
        return err
    }
    

    API reference: StateMigrationArgs · StateMigrationResult.

    See the state migrations guide for a complete example.

    Behavior

    Callbacks run during previews and updates when prior state exists. They must be idempotent and return no result when the state no longer needs migration. They rewrite state without performing provider operations.

    Callbacks must preserve managed resource identity, lifecycle safety flags, and secret envelopes. They must not perform Pulumi runtime operations or wait for unresolved outputs.

    See State migrations for the full contract, restrictions, and complete examples.

      The infrastructure as code platform for any cloud.