driftctl: Terraform Drift Detection and IaC Coverage for AWS, Azure, GCP and GitHub
Detect, track and alert on infrastructure drift
At a glance
- What is it?
- driftctl is a Go CLI from Snyk that scans cloud accounts, compares them against Terraform state and code, and reports unmanaged resources and drift. It is in maintenance mode, so adoption means accepting a frozen feature set.
- Who is it for?
- Adopt driftctl if you already run Terraform and want a read-only, single-binary way to see which cloud resources fall outside your state, with JSON output you can diff between runs. Do not adopt it expecting new providers, new resource types or fixes: the README states the project is in maintenance mode and that contributions cannot be promised a review.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 10 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What problem driftctl solves, and who ends up using it
Terraform only knows about the resources recorded in its state file. Anything created outside that path, whether through a cloud console, an authenticated application or a script, simply does not appear when you run terraform plan. The README frames this as a blind spot: "Infrastructure drift is a blind spot and a source of potential security issues." The project's answer is to invert the comparison. Instead of asking Terraform what it would change, driftctl enumerates what actually exists in the cloud account and asks which of those resources have no counterpart in your Terraform state or code.
The audience follows from that design. It is for platform and infrastructure teams that already manage a meaningful share of their estate with Terraform and want to know what percentage they are missing. The README borrows a testing metaphor for this: coverage is tracked for unit tests, so why not for infrastructure as code. Teams that have never adopted Terraform get little from driftctl, because there is no state to compare against and every resource would simply be reported as unmanaged. The tool is also read-only by design, so it is not a remediation engine. It tells you what diverged; a human or a pipeline decides what to do about it.
How driftctl builds its picture of your infrastructure
The mechanism is a three-way join. First, driftctl reads your Terraform state and code to build a list of resources Terraform believes it owns. Second, it queries the cloud provider's APIs directly to enumerate what is actually deployed. Third, it diffs the two sets and classifies the result: resources present in the cloud but absent from state are unmanaged, and resources whose attributes no longer match the code are drifted.
The dependency list in go.mod shows how that enumeration is implemented per provider. AWS is covered through github.com/aws/aws-sdk-go, Azure through a set of arm* modules such as armcompute, armnetwork and armstorage plus azidentity for authentication, and Google Cloud through cloud.google.com/go/asset, which is the Cloud Asset Inventory API. GitHub is also listed as a supported provider in the README. Terraform handling relies on hashicorp/terraform v0.14.0, hashicorp/terraform-exec and hashicorp/hcl/v2, and a HashiCorp go-plugin dependency suggests provider binaries can be loaded to read state and schemas. The diff itself is computed with github.com/r3labs/diff/v2, and ignore rules are matched with github.com/bmatcuk/doublestar/v4 glob patterns.
The practical consequence of using Cloud Asset Inventory for GCP is that driftctl does not walk every GCP service individually; it depends on what that API exposes and how fresh it is. For AWS and Azure, the coverage is whatever the SDK calls in the repository implement. The README does not publish a coverage matrix, so the honest position is that you should test against your own account before trusting a clean report.
Installing driftctl and running a first scan
The README points to docs.driftctl.com/installation for install instructions rather than listing package manager commands inline, and it also ships a Dockerfile, so building a container image from the repository is a supported path. The Dockerfile is a two-stage build: a golang:1.23 builder stage runs make release with SINGLE_TARGET=true, and the resulting binary is copied into an alpine:3.21.2 image with driftctl as the entrypoint.
docker build -t driftctl .
docker run --rm -v ~/.aws:/root/.aws driftctl scanThe first command builds the image from the repository; the second mounts your AWS credentials into the container and runs a scan. The README does not document the exact credential paths for Azure or GCP, so treat the AWS mount above as the shape of the invocation rather than a universal recipe. If you already have credentials configured in your environment, passing them through as environment variables is the alternative.
A scan is also configurable through a .driftctl.yml file and through environment variables, which is how you would ignore resources you have decided are acceptable. The README lists ignoring resources as a feature and multiple output formats as another, which matters for CI: a JSON output can be diffed or fed into a dashboard, while the human-readable output is for a terminal. The README does not spell out the full config key list, so check the documentation site before writing a config file you intend to keep.
Where driftctl stops being the right tool
The largest limitation is stated by the project itself. The README opens with: "This project is now in maintenance mode. We cannot promise to review contributions." The most recent release listed is v0.40.0 from 2023-12-01, and the README still carries a beta warning saying the tool "will evolve in the future with potential breaking changes." A frozen beta is an awkward place to be. New AWS services, new Azure resource types and new Terraform language features will not be added by the maintainers, so your coverage gap grows over time rather than shrinking.
There is a second, structural limitation. The tool depends on github.com/hashicorp/terraform v0.14.0 and terraform-exec v0.14.0. Modern Terraform releases have moved well past that, and while the repository's go.mod declares go 1.23.0, the Terraform libraries it pins are old. If your workflow depends on state produced by a recent Terraform version, compatibility is something you have to verify rather than assume. The README does not document a supported Terraform version range.
Finally, driftctl is the wrong tool for remediation and for non-Terraform IaC. It reports; it does not import resources into state or delete them. If your estate is managed with Pulumi, CloudFormation or CDK, there is no state model for driftctl to compare against, and the comparison it performs does not apply.
driftctl compared with terraform plan and cloud-native inventory tools
The obvious alternative is terraform plan itself. The difference in approach is direction of comparison. Plan starts from your code and state and asks what Terraform would change to reach the declared configuration; it can only see resources it already knows about. driftctl starts from the cloud account and asks what exists that Terraform does not know about. Those are complementary questions, and a team running only plan will never see a resource that was never imported.
Cloud-native inventory services are the other alternative, and here driftctl's value is the join rather than the enumeration. AWS Config, Azure Resource Graph and GCP Cloud Asset Inventory can all tell you what exists. None of them knows what your Terraform state claims, so none of them can label a resource as unmanaged relative to your IaC. driftctl's contribution is exactly that mapping, plus the coverage percentage that falls out of it.
A third comparison is with policy tools that evaluate resources against rules. Those answer whether a resource is configured acceptably. driftctl answers whether a resource is accounted for at all. A bucket with public access and a bucket missing from state are different failures, and only the second one is driftctl's subject.
Maintenance, upgrade cost and licence
The maintenance picture is the single most important fact for an adoption decision. The repository is not archived, and the last push was on 2026-09-21. That is recent activity, but the README's maintenance-mode notice and the release history point in the same direction: v0.38.2 in January 2023, v0.39.0 in June 2023, v0.40.0 in December 2023, and nothing listed after that. Commits may continue without tagged releases, which means you cannot rely on a version number to know what you are running. If you build from source or from the Dockerfile, you get whatever is on the default branch at build time.
Upgrade cost is therefore mostly your own. The README invites forking: "Please feel free to fork the project to apply any changes you might want to make." A fork means owning a Go codebase with per-provider SDK integrations and a Terraform plugin dependency, which is a real commitment. Pinning a released binary avoids that but freezes your provider coverage at the state of that release.
The licence is Apache-2.0, as stated in the repository metadata and shown by the licence badge in the README. Apache-2.0 permits commercial use, modification and redistribution, and includes an explicit patent grant. It also requires that you preserve notices and state significant changes when you redistribute. Whether that fits a fork you ship internally is a question for your own legal review, not something this article can settle.
Editorial conclusion
Adopt driftctl if you already run Terraform and want a read-only, single-binary way to see which cloud resources fall outside your state, with JSON output you can diff between runs. Do not adopt it expecting new providers, new resource types or fixes: the README states the project is in maintenance mode and that contributions cannot be promised a review. Before rolling it out, verify that the resource types you care about are covered for your provider, and check that your Terraform version is compatible with the bundled hashicorp/terraform v0.14.0 dependency.
Frequently asked questions
How does driftctl detect drift?
It scans the cloud provider APIs to enumerate deployed resources, reads your Terraform state and code, and diffs the two sets. Resources in the cloud with no counterpart in state are reported as unmanaged, and resources whose attributes no longer match are reported as drifted.
How can I fix drift in Terraform?
driftctl itself does not fix anything; it reports drift and unmanaged resources. The README describes it as a CLI that warns of infrastructure drift, so remediation stays with your normal Terraform workflow, such as importing resources into state or updating configuration.
What does configuration drift mean for Terraform users?
The README describes drift as arising from causes such as team members creating or updating infrastructure through a web console without backporting the changes to Terraform, or from unexpected actions by authenticated apps and services. In practice it means the deployed infrastructure no longer matches what your Terraform state and code describe.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/snyk-driftctl)