Running your program on refresh and destroy
By default, pulumi refresh and pulumi destroy do not execute your program. They operate on stack configuration and the resources already recorded in state. Because the program is not run, stack config is also not validated against the project’s config schema. The --run-program flag opts in to running your program first, so the operation sees whatever your program computes at runtime — provider credentials, dynamic resources, or updated provider inputs.
Reach for --run-program whenever the values that refresh or destroy depend on are produced by code rather than persisted in state. The two most common situations are dynamic credentials and provider upgrades.
Refreshing or destroying with expired credentials
Most cloud credentials are short-lived: OIDC-issued tokens and STS session credentials expire on the order of minutes to hours, and credentials brokered through a secrets manager are often similarly time-bound. When pulumi up runs, the program fetches a fresh credential and Pulumi records the resulting provider configuration in state. The credential is not re-fetched on later operations.
A few hours or days later, running pulumi refresh or pulumi destroy reuses that recorded provider configuration. The token has expired, the operation fails, and the failure looks like an auth error from the cloud rather than a stale-credential problem.
Add --run-program to re-run your program so the provider gets a fresh credential:
pulumi refresh --run-program
pulumi destroy --run-program
Removing spurious diffs after a provider upgrade
Major-version provider releases typically change resource schemas: property names and types shift, deprecated fields disappear, and the inputs the provider expects look different from what is currently in state. Running pulumi refresh after a major provider update without running the program can surface spurious diffs that reflect schema differences rather than real drift in the cloud.
Running the program gives the new provider the inputs it needs to compute a clean diff between your program’s intent and the cloud state. After upgrading a provider’s major version, run:
pulumi up --refresh --run-program
The AWS provider 6.x → 7.x migration guide prescribes exactly this command for that reason. The same pattern applies to any provider upgrade where the schema changes — Azure, GCP, Kubernetes, or any other.
Config validation
Stack config validation is tied to whether the program runs. By default when Pulumi runs your program, it validates the stack’s config against the project’s config schema — erroring on missing required keys and type-checking values. When the program is not run, no config validation takes place.
This means:
pulumi refreshandpulumi destroyskip config validation by default, because they do not run the program. Project-level config defaults are still applied; only validation is skipped.- Passing
--run-programtorefreshordestroyruns the program and therefore re-enables config validation. pulumi upandpulumi previewalways run the program, so they validate config by default.
To run the program but still skip config validation, use --skip-config-validation:
pulumi up --skip-config-validation
pulumi preview --skip-config-validation
pulumi refresh --run-program --skip-config-validation
pulumi destroy --run-program --skip-config-validation
This can be useful for ephemeral or pull-request preview environments, where a stack’s config may legitimately diverge from the project schema between branches and you want the operation to proceed regardless.
Using the flag
--run-program is accepted by pulumi refresh, pulumi destroy, and by pulumi up and pulumi preview when they perform a refresh step (--refresh):
pulumi refresh --run-program
pulumi destroy --run-program
pulumi up --refresh --run-program
pulumi preview --refresh --run-program
To set it once per shell or in CI, use the equivalent environment variable:
export PULUMI_RUN_PROGRAM=true
See Pulumi CLI environment variables for the full list.
Related uses
- Resource hooks. Delete hooks require
--run-programonpulumi destroy— without it, Pulumi cannot register the hooks before deletion and the operation fails. See Deletions and delete hooks. - Dynamic providers. Programs that use dynamic providers need the program to run so Pulumi can load the provider’s implementation from your code.
See also
pulumi refresh— CLI reference.pulumi destroy— CLI reference.- Improved refresh and destroy experience for Pulumi IaC — original announcement, with extended examples.
- Resource hooks — when delete hooks force the use of
--run-program.