Use this page when the graph and your real infrastructure disagree, or when entities show a stale/missing drift status.
Terrantula ingests your Terraform state (or Atmos stacks) into entities and stamps each one with where it came from and when. Your state backend remains the source of truth. "Drift" is the gap between what Terrantula last ingested and what the source says now — closing it means re-ingesting, never editing the graph directly.
There are two separate notions of drift; matching your symptom to the right one saves time.
current, stale, or missing, based on the entity's last_synced_at stamp and a 24-hour threshold. This is what you'll hit most.stale ormissingSymptom — GET /entities?driftStatus=stale returns rows, or the dashboard flags entities as stale/missing.
Cause
stale — the entity hasn't been re-synced within the 24h threshold. Its last_synced_at is old. Almost always: you imported once and haven't re-run the import since.missing — the entity exists in Terrantula but was not present in the most recent source scan (e.g. the resource was removed from the state file).Fix
For stale: re-run the import against the same source. Each successful import terraform / import-atmos re-stamps the touched entities with last_synced_at = now(), clearing the stale status.
For missing: decide whether the entity should still exist. If the resource is genuinely gone, drop the leftover entity with --replace (preview with --dry-run first):
--replace deletes only entities previously synced from the same source that are no longer present. It won't touch entities from other sources.
Symptom — you re-imported a source whose state changed, but the entity's properties in Terrantula didn't update.
Cause — the import source's reconciliation policy is human-approval. Under that policy a rescan does not mutate entities; it writes per-entity diffs into pending drift proposals for a human to approve. (New entities are still created directly — creation is non-destructive.) The other policy, auto-update (the default), applies incoming source state directly.
Fix
auto-update.human-approval, approve the pending proposal to apply the diff (or reject to discard it). Proposals are surfaced per source via the import-sources drift rollup; approving applies the stored diff and re-stamps the entity.Symptom — an entity's properties, relationships, or lifecycle state in Terrantula don't match your Terraform.
Cause — the graph reflects the last ingested state. If your Terraform changed after the last import (someone applied a change, added/removed a resource), the graph is simply behind.
Fix — re-ingest. Pull fresh state and re-import:
Do not try to fix the discrepancy by editing the entity in the dashboard — the UI is read-only and can't write entity properties, lifecycle states, or relationships. The correct direction is source → Terrantula (re-import) for observed state, and Terrantula → source → your CI (an Action's PR) for intended changes.
Symptom — you want drift surfaced continuously, not only when you remember to re-import.
Cause — Terrantula does not ship a built-in scheduler. Rescan is a plain HTTP endpoint your own scheduler calls.
Fix — wire any self-hosted scheduler (cron, a GitHub Actions / GitLab CI schedule, an Atmos workflow, a systemd timer) to re-read the source and re-import on an interval. Because import terraform / import-atmos register and refresh the import-source record on every run, a scheduled re-import gives you an updated drift rollup with no glue code. This path runs entirely against the Apache 2.0 backend — no SaaS dependency.
A rescan applies declarative entity state against Terrantula's catalog so the graph matches what the source reports. It never runs terraform apply. Actual infrastructure changes still flow through Actions → PRs → your CI.
Symptom — entities imported before import-source tracking existed don't show in a per-source drift rollup, even though they appear under GET /entities?driftStatus=….
Cause — those entities were sync-stamped but have no registered import-source row, so the per-source rollup (which matches on source_uri) skips them. The direct driftStatus filter still works.
Fix — re-run import terraform / import-atmos once against the same source. Registration is idempotent on (project, env, source URI) and backfills the row on the next run, after which the entities appear in the source's drift rollup.
--replace details.--replace and re-import invocations.