database schema drift detection with atlas

database schema drift detection with atlas

Block deployments on drifted databases. Detect out-of-band changes within minutes.

The Problem

Schema drift is the silent killer of versioned migrations

Versioned migrations are fast because they only track which files have already run, then execute the next one in order. They never re-inspect the database, never replan, never diff. By the time a migration breaks, drift has been compounding for weeks.

Trust without verificationMigration runners only track which files have run, then execute the next one blindly. They never re-inspect the database itself, so drift is invisible until something breaks.
Every shortcut bypasses reviewEmergency hotfixes, manual ALTERs, ORM auto-migrators, second-tool writers. Each one lands without a PR or a CI run.
Half-migrated productionA migration written against an expected state hits a different reality, fails halfway, and leaves a database nobody knows how to recover.
Chain of custody breaksSOC 2, ISO 27002, PCI DSS, and HIPAA all require a record of every change. Drift is, by definition, an unrecorded change.
deploy@prod-postgres
HALF-MIGRATED
$ tail -n 4 /var/log/postgresql/ddl.log
03:41:12[admin]ALTER TABLE orders DROP COLUMN legacy_id;
03:42:38[deploy_bot]GRANT ALL ON *.* TO analytics_role;
03:43:51[unknown]ALTER ROLE superuser WITH SUPERUSER;
04:01:07[admin]CREATE TABLE users_history (id int);
$ pg_dump --schema-only prod | diff migrations/state.sql -
--- migrations/state.sql (expected)
+++ prod (actual)
@@ -0,0 +1,3 @@
+CREATE TABLE "users_history" (
+ "id" integer
+);
# 6 hours later, the scheduled deploy runs...
$ ./deploy.sh
[migrator] applying version 20260423130000
-> ALTER TABLE users ADD COLUMN email text;
-> CREATE TABLE users_history (id integer NOT NULL);
ERROR: relation "users_history" already exists
[migrator] aborted mid-batch · database left in partial state
How Atlas solves this
Pre-apply drift check

Verify before every migration runs

Before applying any migration files, Atlas makes sure your database wasn't silently changed outside of migrations, a manual ALTER, an emergency hotfix, an ORM auto-migration. If it was, the deploy is aborted and the exact diff is shown so you know what drifted.

Synchronous pre-execution gateAtlas inspects the database itself, before the migration runner touches a single file. The gate is a real-time check, not a separate scan job.
Single-block setupEnabled with one block of configuration. No agents to deploy, no separate services to operate, no schedule to maintain.
Per-environment policiesHard-fail in production, advisory in staging, off in local. Switch behavior based on the environment without forking the config.
atlas migrate apply
drift detected
migrate to v20260423130000against postgres://prod-db
3 changes
Pre-execution checks
drift against v20260423120000
atlas.hcl:10 · drift detected
3.2ms
What drifted
@@ -14 +14 @@ "orders"
14
- "legacy_id" varchar(64),
@@ -42,0 +43,3 @@
43
+CREATE TABLE "users_history" (
44
+ "id" bigint NOT NULL
45
+);
@@ -78,0 +79,1 @@
79
+GRANT ALL ON SCHEMA public TO "analytics_role";
Migration safely aborted
No SQL was executed against the database. Revert the change, or capture it in a new migration.
Continuous Drift Monitoring

See drift the moment it happens

The pre-apply check guards the next migration. Continuous monitoring is the radar between deploys, so an out-of-band change surfaces in seconds, not after the next failed deploy.

Periodic inspectionScans each database on the schedule you set, hourly, every five minutes, or as often as the environment needs.
Alerts where your team livesSlack, webhooks, in-product. The moment an unauthorized change lands in the database, your on-call channel hears about it.
Full diff and audit historyEvery event keeps the SQL/HCL diff and ERD in a timeline, so "when did this start" is one click away.
#acme-oncall
Atlas Bot2:45 PM
⚠️Drift detected on prod-postgres

Production database schema differs from expected state at v20260423120000.

schemaTable users_history added outside migration
columnColumn orders.legacy_id removed in production
grantGRANT ALL ON SCHEMA public TO analytics_role
Shift Left. Watch Right

Preventive and detective controls, in one workflow

The pre-apply check is the safety belt at deploy time. Continuous monitoring is the radar between deploys. Together they cover the full window in which drift can do damage.

One week in production
MonTueWedThuFri

The two highlighted moments show each control catching drift.

deploy v23Mon 09:14Pre-apply check passed
deploy v24 BLOCKEDWed 11:08Drift from Tue not yet remediated
drift remediatedWed 14:21Migration written, GRANT folded back
deploy v24Thu 10:02Pre-apply check passed, clean apply
drift detectedFri 15:47New table created out-of-band

Every change in production is either authorized by review, or flagged within minutes.

SOC 2ISO 27002PCI DSSHIPAA
vs Liquibase & Flyway

What other tools miss

Atlas covers drift across three dimensions where Liquibase and Flyway leave gaps.

01

Built-in, two ways

Drift detection runs as a pre-apply check inside the migration pipeline and as a continuous monitoring layer between deploys.

vs. Liquibase and Flyway ship a drift report only. Separate command, no monitoring layer.

02

Every schema object

Every schema change and every security change. From tables, columns, and views to users, roles, and permissions.

vs. Limited to the schema changes each tool models natively. Security changes (users, roles, grants, RLS) fall outside the diff.

03

Every supported driver

PostgreSQL, MySQL, SQL Server, MariaDB, Oracle, SQLite, ClickHouse, Snowflake, Redshift, Spanner, Databricks, CockroachDB, Aurora DSQL, Azure Fabric, and more.

vs. Coverage varies per database. Many drivers limited or unsupported.

Block drift at deploy. Detect it between deploys.