Drift detection and remediation
This page covers the drift detection and remediation capabilities that Pulumi Cloud manages for you: scheduled drift runs, the Drift tab, automatic remediation, and notifications. For the conceptual foundation — the difference between desired, current, and actual state, how to choose between remediation and adoption, and the underlying CLI workflow — see Detecting and reconciling drift.
Drift is the gap between the actual state of your cloud resources and the state Pulumi has recorded for them. It most often comes from manual, out-of-band changes (“click-ops”) or from changes a cloud resource makes over its own lifecycle. Pulumi Cloud detects drift by running a preview-only refresh against your stack, and it can remediate drift — re-applying your program so the cloud matches your desired state — automatically.
To use drift detection and remediation with Pulumi Deployments, you must first configure the deployment settings for your stack.
Running drift detection from the CLI
Any preview of a refresh counts as a drift detection run in Pulumi Cloud. To run drift detection from the CLI, use pulumi refresh --preview-only, or pulumi refresh, which runs a preview (creating the drift run) before performing the actual refresh.
After your run completes, you can see it in the Drift tab for your stack, alongside any scheduled runs.
For the full CLI workflow — detection, remediation, adoption, and --expect-no-changes for CI — see Detecting and reconciling drift.
Pulumi Cloud UI
Running via Click to Deploy
You can run a drift or remediate-drift run ad hoc from your stack using the Click to Deploy menu, which lists the operations available for the stack. Select Detect drift to run a preview-only refresh, or Remediate drift to reconcile any detected drift. Both runs appear in the Drift tab when they complete.
Drift tab
The Drift tab on the stack page is where every drift run surfaces, no matter how the run started — from the CLI, from Click to Deploy, or on a schedule. When the stack is currently in a drifted state, a warning bell icon appears on the tab. If a run detects drift, its information card includes a diff summary of the changes.
Configuring drift detection on a schedule
To set up drift detection and remediation in the Pulumi Cloud console, follow these steps:
- Ensure deployment settings are configured on the stack (see the docs).
- Navigate to Stack > Settings > Schedules.
- Select Drift.
- (Optional) Turn on auto-remediation if applicable. With auto-remediation enabled, Pulumi Cloud runs
pulumi up --refreshafter a detection run finds drift, reconciling the cloud back to your program’s desired state. - Set the schedule using a cron expression.
- Save the schedule.
Configuring notifications for drift detection
You can route drift notifications to Slack, Microsoft Teams, and more using the Pulumi Webhooks integration.
- Navigate to Stack > Settings > Webhooks.
- Select your desired webhook format.
- Give your webhook a display name, destination URL, and optional secret.
- All events include drift events, but you can also filter the events down to drift events only.
Summary of drift detection and remediation events
- Drift detected - A drift run detected drift.
- Drift detection succeeded - A drift run succeeded, regardless of whether it detected drift or not.
- Drift detection failed - A drift run failed to finish.
- Drift remediation succeeded - A drift remediation run succeeded.
- Drift remediation failed - A drift remediation run failed to finish.
Setting it up via the REST API
For those who prefer to automate and script their infrastructure tasks, drift detection and remediation can be configured programmatically using HTTP requests. The available endpoints are:
- Create a drift schedule
- Get a drift schedule
- Update or delete a drift schedule
- Pause or resume a drift schedule
- List all schedules (includes raw Pulumi operations and time-to-live schedules)
Below is an example of setting up drift detection and remediation on a stack. See the Pulumi Deployments REST API documentation for more details on configuring drift detection and remediation programmatically.
Create a drift detection and remediation schedule:
curl -H "Accept: application/vnd.pulumi+json" \
-H "Content-Type: application/json" \
-H "Authorization: token $PULUMI_ACCESS_TOKEN" \
--request POST \
--data '{"scheduleCron":"0 0 * * *","autoRemediate":true}' \
https://api.pulumi.com/api/stacks/{organization}/{project}/{stack}/deployments/drift/schedules
Setting it up via the Pulumi Service Provider
The Pulumi Service Provider allows you to set up automated drift detection and remediation in source control.
import * as pulumi from "@pulumi/pulumi";
import * as pulumiservice from "@pulumi/pulumiservice";
const organizationName = "my-org";
const projectName = "my-project";
const stackName = "production";
// Creating a DriftSchedule for automatically running drift detection
const driftDetectionSchedule = new pulumiservice.DriftSchedule("driftDetectionSchedule", {
organization: organizationName,
project: projectName,
stack: stackName,
scheduleCron: "0 0 * * *", // Run drift detection daily at midnight
autoRemediate: true, // Automatically remediate any drift detected
});
export const driftScheduleId = driftDetectionSchedule.scheduleId;
import pulumi
import pulumi_pulumiservice as pulumiservice
organization_name = "my-org"
project_name = "my-project"
stack_name = "production"
# Create a drift detection schedule
drift_detection_schedule = pulumiservice.DriftSchedule("driftDetectionSchedule",
organization=organization_name,
project=project_name,
stack=stack_name,
schedule_cron="0 0 * * *", # Run drift detection daily at midnight
auto_remediate=True) # Automatically remediate any drift detected
pulumi.export('driftScheduleId', drift_detection_schedule.schedule_id)
package main
import (
"github.com/pulumi/pulumi-pulumiservice/sdk/go/pulumiservice"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
driftDetectionSchedule, err := pulumiservice.NewDriftSchedule(ctx, "driftDetectionSchedule", &pulumiservice.DriftScheduleArgs{
Organization: pulumi.String("my-org"),
Project: pulumi.String("my-project"),
Stack: pulumi.String("production"),
ScheduleCron: pulumi.String("0 0 * * *"), // Run drift detection daily at midnight
AutoRemediate: pulumi.Bool(true), // Automatically remediate any drift detected
})
if err != nil {
return err
}
ctx.Export("driftScheduleId", driftDetectionSchedule.ScheduleId)
return nil
})
}
using Pulumi;
using PulumiService = Pulumi.PulumiService;
class Program
{
static Task<int> Main() => Deployment.RunAsync(() => {
var driftDetectionSchedule = new PulumiService.DriftSchedule("driftDetectionSchedule", new PulumiService.DriftScheduleArgs
{
Organization = "my-org",
Project = "my-project",
Stack = "production",
ScheduleCron = "0 0 * * *", // Run drift detection daily at midnight
AutoRemediate = true, // Automatically remediate any drift detected
});
return new Dictionary<string, object?>
{
{ "driftScheduleId", driftDetectionSchedule.ScheduleId }
};
});
}
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.pulumiservice.DriftSchedule;
import com.pulumi.pulumiservice.DriftScheduleArgs;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
private static void stack(Context ctx) {
var driftDetectionSchedule = new DriftSchedule("driftDetectionSchedule", DriftScheduleArgs.builder()
.organization("my-org")
.project("my-project")
.stack("production")
.scheduleCron("0 0 * * *") // Run drift detection daily at midnight
.autoRemediate(true) // Automatically remediate any drift detected
.build());
ctx.export("driftScheduleId", driftDetectionSchedule.scheduleId());
}
}
name: drift-detection-setup
runtime: yaml
description: Setup of automated drift detection with Pulumi
resources:
driftDetectionSchedule:
type: pulumiservice:index:DriftSchedule
properties:
organization: my-org
project: my-project
stack: production
scheduleCron: "0 0 * * *" # Run drift detection daily at midnight
autoRemediate: true # Automatically remediate any drift detected
outputs:
driftScheduleId: ${driftDetectionSchedule.scheduleId}
See the Pulumi Service Provider documentation for more details on managing drift detection and remediation in source control.
See also
- Detecting and reconciling drift - the conceptual foundation and the CLI workflow.
- Schedules - schedule any Pulumi operation, not just drift.
- Webhooks - route drift events to Slack, Microsoft Teams, or any HTTP endpoint.
Thank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.