CloudFormation Drift Detection: Practical Guide
Published on · Updated on
Reworked the detection and remediation workflow for current drift-aware change sets and coverage limits.
AWS CloudFormation drift detection compares the current configuration of stack resources with the expected values in the stack template and its parameters. Start a stack check, wait for its asynchronous operation to finish, then inspect each checked resource's differences. Detection reports drift; it does not fix it. Coverage is limited to supported resource types and properties explicitly set in the template, so an IN_SYNC result is not proof that every resource or setting in your account matches your intent. AWS explains the comparison and its limits.
What CloudFormation drift detection checks
A resource has drifted when a checked live property differs from the expected template value, or when the resource has been deleted. The stack is marked DRIFTED if at least one resource drifts. CloudFormation checks stack-managed resources; it is not an account-wide inventory of objects created outside the stack.
Resource and property coverage
Support varies by resource type and property. Check AWS's current resource type support table before relying on a scan. Provisionable private resource types can also support drift detection when their default type version is registered in the account. Even when a resource type is supported, some properties cannot be compared: CloudFormation only checks values explicitly set in the template or through parameters, and services may not return sensitive or otherwise uncomparable values. Defaults are not tracked when you omit a property; explicitly set a value, including a service default, if you need drift detection for it. AWS also documents specific comparison gaps and edge cases such as the KMSKeyId property and service-populated array values.
Nested stacks need their own checks
A drift check on a parent stack does not inspect the resources inside its nested stacks. Run drift detection directly on each nested stack whose resources you need to check. The parent may therefore be IN_SYNC while a child stack has not been checked.
Check StackSets with their own drift operation
For stacks deployed through CloudFormation StackSets, use the StackSet drift workflow to check its member stack instances across accounts and Regions. A check of one ordinary stack does not cover the other instances, and detection reports drift without applying a fix. See AWS's StackSets drift guidance.
Run a drift detection operation
Check permissions and stack state
For stack detection, the caller needs cloudformation:DetectStackDrift, cloudformation:DetectStackResourceDrift, and cloudformation:BatchDescribeTypeConfigurations, plus read permissions for the supported resource APIs in that stack. For example, detecting drift on an EC2 instance requires ec2:DescribeInstances. Grant the relevant read actions for the resource types you actually check; a CloudFormation permission alone is not enough. The caller also needs permission to describe the detection operation and retrieve resource drift results. AWS lists these prerequisites in its drift detection considerations.
CloudFormation accepts stack drift checks when a stack is in CREATE_COMPLETE, UPDATE_COMPLETE, UPDATE_ROLLBACK_COMPLETE, or UPDATE_ROLLBACK_FAILED. Only one drift detection can run for a stack at a time, so wait for an existing check to finish before starting another.
Use the console or check one resource
In the CloudFormation console, select the stack, choose Stack actions → Detect drift, wait for completion, then open View drift results. To check a single resource, use its logical ID:
aws cloudformation detect-stack-resource-drift \
--stack-name my-stack \
--logical-resource-id MyBucket
This returns that resource's drift status and, when a difference is found, expected and actual properties. To check a whole stack, use the asynchronous CLI workflow below.
Start, poll, and inspect a stack check
detect-stack-drift returns a detection ID while the check runs. Poll that ID until DetectionStatus reaches a terminal state; after DETECTION_COMPLETE, query the resource results. The CLI commands below work in Bash or Zsh:
detection_id=$(aws cloudformation detect-stack-drift \
--stack-name my-stack \
--query StackDriftDetectionId \
--output text)
aws cloudformation describe-stack-drift-detection-status \
--stack-drift-detection-id "$detection_id"
# Repeat the status command until DetectionStatus is terminal.
# If it is DETECTION_COMPLETE, inspect the resource results:
aws cloudformation describe-stack-resource-drifts \
--stack-name my-stack
For a large result, the describe command is paginated; the AWS CLI follows result pages unless you disable pagination. Confirm the result timestamps are from the check you just started before acting on them. The AWS stack workflow documents the console and CLI steps.
When a check fails or looks incomplete
DETECTION_FAILED means at least one resource could not be checked; results can still be available for resources that succeeded. Read DetectionStatusReason, inspect per-resource status and timestamps, and correct the underlying issue before treating the scan as complete. Missing read permissions for a supported resource can fail its check. Unsupported resource types or properties are coverage gaps, while an ineligible stack state or an existing check can prevent a new operation. Do not interpret partial results as a clean stack. AWS's status API reference defines the operation states and partial-result behavior.
Read the statuses at the right level
CloudFormation reports an operation status, a stack drift status, and resource drift statuses. These describe different things. For example, DETECTION_COMPLETE says the operation finished for resources that support detection; it does not mean all resources were checked.
| Level | Status | Meaning |
|---|---|---|
| Operation | DETECTION_IN_PROGRESS | The check is still running. |
| Operation | DETECTION_COMPLETE | The check finished for supported resources in the requested scope; unsupported resources remain unchecked. |
| Operation | DETECTION_FAILED | At least one resource check failed. Some successful resource results may still be available. |
| Stack | DRIFTED | At least one checked resource is drifted. |
| Stack | IN_SYNC | Checked, supported properties match expected values; this does not cover omitted defaults, unsupported properties, or unchecked nested stacks. |
| Stack | NOT_CHECKED | CloudFormation has not checked the stack. |
| Stack | UNKNOWN | CloudFormation could not determine drift for a resource. Read the operation reason and resource results. |
| Resource | MODIFIED or DELETED | A checked property differs, or the resource no longer exists. |
| Resource | IN_SYNC | The resource's checked properties match its expected values. |
| Resource | UNKNOWN | CloudFormation could not run drift detection for the resource; read its drift status reason. |
| Resource | UNSUPPORTED | The type has no actual-state comparison in a drift-aware change set; see AWS's support limitations. |
| User Guide status | NOT_CHECKED | Used for a resource that has not been checked; the current StackResourceDrift API says it does not return this value. |
DRIFTED is a stack status, not a resource status. For each drifted resource, review its logical and physical IDs, property paths, expected values, actual values, and last-check timestamp. Before calling a difference a problem, account for service defaults and equivalent values that may be serialized differently. Unsupported resources may be absent from drift results. Compare the stack's resources with AWS's live support table rather than interpreting a missing result as IN_SYNC. See AWS's status definitions, resource drift API, and resource support table.
Choose how to reconcile drift
Detection identifies a mismatch; remediation is a separate deployment or resource change. First decide which state is intended. A live change may be a temporary incident response, an approved change that has not reached the template, or an unsafe modification. Confirm with the resource owner and change history before selecting a direction. For a broader process for keeping templates reviewed and tested, see common AWS infrastructure-as-code pitfalls.
Preview with a drift-aware change set
CloudFormation supports drift-aware change sets. With deployment mode REVERT_DRIFT, the change set compares actual state, the previous deployment state, and the desired template state. If the template still contains the old value, executing the change set can restore that value on the resource. If you first update the template to an approved live value, the change set can bring the template record into agreement without changing that property on the resource, provided the live value remains unchanged before execution. The feature has coverage limits: unsupported types fall back to a template-to-template comparison; write-only properties use previous deployment values; AWS-managed properties and external tag keys receive special handling; immutable properties are not reconciled by this mode. Review the reported drift and ignored properties rather than treating the mode as an automatic repair. AWS documents these behaviors in its drift-aware change set guide.
Use an AWS CLI version whose create-change-set command supports --deployment-mode. If the stack has parameters, supply each approved value explicitly or use ParameterKey=...,UsePreviousValue=true to preserve its current value; otherwise, a missing value can fall back to a template default. The current AWS CLI reference documents these options.
aws cloudformation create-change-set \
--stack-name my-stack \
--change-set-name review-drift-reconciliation \
--change-set-type UPDATE \
--template-body file://approved-template.yaml \
--deployment-mode REVERT_DRIFT
aws cloudformation describe-change-set \
--stack-name my-stack \
--change-set-name review-drift-reconciliation
When the template contains IAM resources, acknowledge the required capability: CAPABILITY_IAM, or CAPABILITY_NAMED_IAM when it creates named IAM resources. Creating a change set starts an asynchronous operation. Repeat describe-change-set and wait for Status=CREATE_COMPLETE before reviewing; if creation fails, inspect its status reason. Then inspect every affected resource and property, including whether CloudFormation will replace or delete a resource. Execute only after the proposed result is approved. A change set is a preview, not a guarantee that deployment will succeed.
Plan for replacement, deletion, and imports
Some property changes require resource replacement. Check the change set's Replacement field and the resource type's update behavior before execution: replacement creates a new physical resource and can interrupt dependent workloads or put stored data at risk. Back up data and plan cutover. Where appropriate, configure UpdateReplacePolicy to retain the old resource or create a supported snapshot; retained resources and snapshots remain billable and leave CloudFormation's management scope. AWS describes replacement previews and the UpdateReplacePolicy options.
Resource import is for taking an existing, supported resource into a stack's management, not a general drift fix. An import requires a template that describes the stack and an identifier for each resource; each imported resource needs a DeletionPolicy, and the import operation does not change resource properties. After import, run drift detection and align the template with actual state before the next update. AWS details the resource import constraints and a specific drift resolution through import procedure.
Track broader resource history separately
For recurring stack evaluations, AWS Config provides the managed cloudformation-stack-drift-detection-check rule. It runs CloudFormation's DetectStackDrift operation for each stack in scope and supports configuration-change and periodic triggers. Configure the rule's IAM role and scope; AWS notes a 15-minute rule execution limit, so a large account may need tag-based groups. The rule uses CloudFormation's drift results and does not extend their resource, property, default-value, or nested-stack coverage. See the AWS Config rule reference. For broader inventory and configuration history, see our AWS Config inventory and change-tracking guide.
FAQs
How do I check a stack for drift?
Run aws cloudformation detect-stack-drift --stack-name my-stack, poll the returned detection ID with describe-stack-drift-detection-status, and inspect resource details with describe-stack-resource-drifts after the operation completes. The console offers the same stack-level workflow.
Does drift detection fix the difference?
No. It reports current differences. To reconcile them, decide whether the template or the live resource should change, create and review an appropriate change set, and execute only the reviewed change. Drift-aware change sets can make that comparison more useful, but their coverage and replacement limits still apply.
Does IN_SYNC mean every setting is correct?
No. It means the properties CloudFormation checked match the expected values. Unsupported resource types and properties, omitted default values, and nested stacks not checked remain outside that conclusion.