Terraform reports a successful apply. No changes. Plan is clean. Everything looks good.

Meanwhile, someone manually changed a security group in the console three weeks ago. The load balancer's health check port is wrong. The database is accepting connections on a subnet it should not be touching.

Terraform does not know. You do not know. This is state drift, and it is one of the most dangerous conditions in infrastructure management because it is invisible until something breaks.

How State Drift Happens

Terraform maintains a state file that represents what it believes about your infrastructure. When you run terraform apply, it compares the state file to your configuration and makes changes to close the gap.

The state file is not a live view of your cloud. It is a snapshot of what Terraform last saw.

Drift happens when the real cloud diverges from the state file without Terraform's involvement. Common causes:

Manual console changes. An engineer tweaks a setting in the AWS console to fix an incident, intending to "update the Terraform later." They forget.

Other automation. A different tool, a lambda, or a vendor integration modifies the same resource Terraform manages.

AWS service updates. AWS occasionally updates default values or adds new attributes to existing resources. Terraform sees these as unexpected state.

Partial applies. A Terraform run fails halfway through. Some resources are updated, others are not. The state file is now partially accurate.

Why terraform plan Does Not Catch It

This is the part that surprises people. terraform plan compares your configuration to the state file. If the state file says your security group has port 443 open, Terraform plans no change, even if the real security group was modified to block port 443.

The command you actually need is terraform plan -refresh-only. This forces Terraform to re-read the actual cloud state before comparing. It is slower. It costs API calls. But it is the only way to detect drift.

Building Drift Detection Into Your Workflow

Run terraform plan -refresh-only on a schedule, not just before applies. A daily or weekly drift detection job that sends alerts when the real cloud diverges from state gives you visibility before the divergence causes an incident.

Driftctl is a dedicated tool for this. It scans your cloud resources and identifies anything that is not managed by Terraform at all, which catches a different class of problem: shadow infrastructure that was never in your state file to begin with.

The root fix is cultural. Manual console changes need a policy. Not "do not do this" but "if you do this, open a PR to update the Terraform within 24 hours." Drift that gets fixed in code within a day is survivable. Drift that accumulates for months becomes a rewrite project.

The Interview Question Version

If someone asks you "how do you handle infrastructure drift?" in an interview, the answer they want covers three things: how drift happens (state file vs reality), how you detect it (refresh-only plans, scheduled checks), and how you prevent it (policy against manual changes, audit logging, automated remediation). Most candidates cover the first and skip the second two.