Faster Schema Tests with PostgreSQL Template Databases
Atlas schema tests run each test group against a fresh copy of your schema on the dev database: Atlas builds the desired schema, runs the group, and tears it down again so nothing leaks between cases. On large schemas, rebuilding the schema for every group dominates the run time. On PostgreSQL, Atlas can instead use a template database, making per-cycle setup near-constant no matter how large the schema is: typically 10x-20x faster end to end, and up to dozens of times faster for larger schemas.
Schema testing and template databases are available only to Atlas Pro users. To use this feature, run:
atlas login
How It Works
With template = true set on the dev block:
- Every test group runs on a fresh copy of the desired schema (plus the optional
baseline). Setup time per group is near-constant, no matter how large the schema is. - All DDL and DML performed by a test is isolated to its own copy and discarded when the group ends.
- Tests marked
parallel = trueshare a single fresh copy, and every non-parallel test gets its own copy, so sequences, inserts, and schema changes never bleed between cases. - Cluster-level role changes are isolated too: roles a test creates are removed, and baseline roles a test alters or drops are restored.
Docker-Managed Dev Database
The simplest way to opt in is to add template = true to a docker "postgres" block and point
your environment's dev at it:
docker "postgres" "dev" {
image = "postgres:18"
template = true
}
env "test" {
src = "file://schema.sql"
dev = docker.postgres.dev.url
}
Given a schema:
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL
);
And a few tests that show the per-group isolation (users_table_exists runs in the shared
parallel copy, while insert_is_isolated and fresh_copy each get their own):
test "schema" "users_table_exists" {
parallel = true
exec {
sql = "SELECT count(*) FROM information_schema.tables WHERE table_name = 'users'"
output = "1"
}
}
test "schema" "insert_is_isolated" {
exec {
sql = "INSERT INTO users (name) VALUES ('alice')"
}
exec {
sql = "SELECT count(*) FROM users"
output = "1"
}
}
test "schema" "fresh_copy" {
exec {
sql = "SELECT count(*) FROM users"
output = "0"
}
}
Run the tests:
atlas schema test --env test
-- PASS: users_table_exists (0.01s)
-- PASS: insert_is_isolated (0.01s)
-- PASS: fresh_copy (0.01s)
PASS
fresh_copy sees zero rows even though insert_is_isolated inserted one because each group ran
on its own fresh copy of the schema.
User-Managed Dev Database
To run against a database you manage yourself (e.g., a shared, pre-warmed PostgreSQL kept
close to your tests) declare a dev "postgres" block with template = true:
dev "postgres" "main" {
url = "postgres://user:pass@dev-server:5432/dev"
template = true
}
env "test" {
src = "file://schema.sql"
dev = dev.postgres.main.url
}
Atlas runs every test group on a fresh copy of the schema and leaves the database as it found it when the run finishes, so the same database can be reused across runs. The database must be dedicated to Atlas and grant Atlas enough privileges to create and drop databases and roles.
Baseline Objects
Some objects must exist before your schema loads and while your tests run, yet are not part of
the schema you are testing (i.e., cluster roles, extensions, or cloud-specific shim functions). Declare
them with baseline, and every test group's copy includes them:
docker "postgres" "dev" {
image = "postgres:18"
template = true
baseline = <<-SQL
CREATE ROLE app_owner;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
SQL
}
Since role changes are isolated per group, a baseline role that a test alters or drops is restored, and a role a test creates is removed. Baseline objects behave as a stable, isolated starting point for every case.
- Template databases are PostgreSQL only; CockroachDB, YugabyteDB, and Aurora DSQL are not supported.
- The dev connection must target a database rather than a single schema (a
search_path-scoped URL is not supported). - The speedup applies across several test groups; a run with a single group sees no benefit.
- A user-managed dev database must be dedicated to Atlas and grant it the privileges needed to create and drop databases and roles.
Next Steps
- Learn the full schema testing syntax in Testing your Schema.
- Test your migration files with Testing Migrations.