Drift-aware change sets are a newer CloudFormation feature that solves a quiet but serious problem: **traditional change sets compare templates, not reality**. If someone made an out-of-band change to a resource (incident response, a console fix), a normal change set won't see it — and on execute, it silently reverts the live change. ## Two-way vs three-way comparison **Traditional change sets** (two-way): `previous template` ↔ `new template`. Drift is invisible. **Drift-aware change sets** (three-way): `actual live state` ↔ `previous deployment state` ↔ `new desired state`. CFN reads each resource's live config via the underlying service APIs at change set creation time. ## What this enables | Capability | Traditional | Drift-aware | |------------|-------------|-------------| | See what the deployment will overwrite | Template diff only | Live-resource diff | | Reset drift without modifying resource | No | Yes — update template to match actual, drift status clears | | Rollback target on failure | Previous template state | **Actual pre-deployment state** | | Preserve out-of-band incident fixes | No | Yes (when appropriate) | | Three-way visibility on all properties | No | Yes | The rollback-target shift is the biggest operational win. Traditional change sets, on failure, roll back to whatever the *template* said before — overwriting any in-flight live changes. Drift-aware preserves what was actually there. ## How CFN classifies "out-of-band" changes Not all drift is bad. Drift-aware change sets distinguish: - **AWS-managed properties** — left alone if you didn't touch them in the template - `AWS::RDS::DBInstance` `EngineVersion` (when AutoMinorVersionUpgrade is on) - `AWS::ApplicationAutoScaling::ScalableTarget` (DynamoDB capacity, ECS desired count) - `AWS::AutoScaling::ScalingPolicy` settings - **Write-only properties** (passwords, secrets) — compared against previous deployment, not live (live values aren't returned by services) - **External tag keys** — preserved if not specified in template (protects ABAC systems) ## CLI invocation ```bash aws cloudformation create-change-set \ --stack-name my-stack \ --change-set-name my-drift-aware-changeset \ --template-body file://updated-template.yaml \ --deployment-mode REVERT_DRIFT \ --capabilities CAPABILITY_IAM ``` The `--deployment-mode REVERT_DRIFT` flag is the toggle. Without it, you get a traditional change set. ## Reading the output `describe-change-set` adds these fields: - `StackDriftStatus`: `DRIFTED` / `IN_SYNC` / `NOT_CHECKED` / `UNKNOWN` - `ResourceDriftStatus`: per resource — `DELETED` / `MODIFIED` / `IN_SYNC` / `NOT_CHECKED` - `BeforeValueFrom`: `ACTUAL_STATE` or `PREVIOUS_DEPLOYMENT_STATE` — tells you whether the "before" value in a property diff comes from live config or last template - `Drift`: object with `PreviousValue`, `ActualValue`, `DriftDetectionTimestamp` - `ResourceDriftIgnoredProperties`: properties where drift is intentionally not reverted, with reasons (AWS-managed, ABAC tag, etc.) ## Limitations - Resource-type support is broad but not universal; unsupported types fall back to two-way comparison - Immutable properties (those that require replacement) cannot be drift-reconciled — replacement is the only path - Cross-stack attachments (an `IAM::Policy` in stack A modifying an `IAM::Role` in stack B) are detected as drift in B and may be reverted ## When to default to drift-aware For any production stack with any non-trivial operational history. The cost is one extra CLI flag; the benefit is never silently overwriting an incident fix. ## Related - [[CFN Change Sets Preview-Execute]] - [[CFN Drift Detection Mechanics and Limits]] - [[CFN Failure Rollback Behavior]]