Atlas is a language-agnostic tool for managing and migrating database schemas using modern DevOps principles. It offers two workflows:
Declarative: Similar to Terraform, Atlas compares the current state of the database to the desired state, as defined in an [HCL], [SQL], or [ORM] schema. Based on this comparison, it generates and executes a migration plan to transition the database to its desired state.
Versioned: Unlike other tools, Atlas automatically plans schema migrations for you. Users can describe their desired database schema in [HCL], [SQL], or their chosen [ORM], and by utilizing Atlas, they can plan, lint, and apply the necessary migrations to the database.
PostgreSQL · MySQL · MariaDB · SQL Server · SQLite · ClickHouse · Redshift · Oracle · Snowflake · CockroachDB · TiDB · Databricks · Spanner · Aurora DSQL · Azure Fabric
macOS + Linux:
curl -sSf https://atlasgo.sh | sh
Homebrew:
brew install ariga/tap/atlas
Docker:
docker pull arigaio/atlas
NPM:
npx @ariga/atlas
See installation docs for all platforms.
atlas schema command offers various options for inspecting, diffing, comparing, planning and applying migrations using standard Terraform-like workflows.atlas migrate command provides a state-of-the-art experience for planning, linting, and applying migrations.Get started with Atlas by following the Getting Started docs.
Inspect an existing database schema:
atlas schema inspect -u "postgres://localhost:5432/mydb"
Apply your desired schema to the database:
atlas schema apply \
--url "postgres://localhost:5432/mydb" \
--to file://schema.hcl \
--dev-url "docker://postgres/16/dev"
Atlas ships with 50+ built-in analyzers that review your migration files and catch issues before they reach production. Analyzers detect destructive changes like dropped tables or columns, data-dependent modifications such as adding non-nullable columns without defaults, and database-specific risks like table locks and table rewrites that can cause downtime on busy tables. You can also define your own custom policy rules.
atlas migrate lint --dev-url "docker://postgres/16/dev"
Test database logic (functions, views, triggers, procedures) and
data migrations with .test.hcl files:
test "schema" "postal" {
# Valid postal codes pass
exec {
sql = "SELECT '12345'::us_postal_code"
}
# Invalid postal codes fail
catch {
sql = "SELECT 'hello'::us_postal_code"
}
}
test "schema" "seed" {
for_each = [
{input: "hello", expected: "HELLO"},
{input: "world", expected: "WORLD"},
]
exec {
sql = "SELECT upper('${each.value.input}')"
output = each.value.expected
}
}
atlas schema test --dev-url "docker://postgres/16/dev"
Manage database roles, permissions, and row-level security as version-controlled code:
role "app_readonly" {
comment = "Read-only access for reporting"
}
role "app_writer" {
comment = "Read-write access for the application"
member_of = [role.app_readonly]
}
user "api_user" {
password = var.api_password
conn_limit = 20
comment = "Application API service account"
member_of = [role.app_writer]
}
permission {
for_each = [table.orders, table.products, table.users]
for = each.value
to = role.app_readonly
privileges = [SELECT]
}
policy "tenant_isolation" {
on = table.orders
for = ALL
to = ["app_writer"]
using = "(tenant_id = current_setting('app.current_tenant')::integer)"
check = "(tenant_id = current_setting('app.current_tenant')::integer)"
}
Manage seed and lookup data declaratively alongside your schema:
CREATE TABLE countries (
id INT PRIMARY KEY,
code VARCHAR(2) NOT NULL,
name VARCHAR(100) NOT NULL
);
INSERT INTO countries (id, code, name) VALUES
(1, 'US', 'United States'),
(2, 'IL', 'Israel'),
(3, 'DE', 'Germany');
Define your schema in any of the 16 supported ORMs. Atlas reads your models and generates migrations:
| Language | ORMs |
|---|---|
| Go | GORM, Ent, Bun, Beego, sqlc |
| TypeScript | Prisma, Drizzle, TypeORM, Sequelize |
| Python | Django, SQLAlchemy |
| Java | Hibernate |
| .NET | EF Core |
| PHP | Doctrine |
Lint, test, and apply migrations automatically in your CI/CD pipeline or infrastructure-as-code workflow:
| Integration | Docs |
|---|---|
| GitHub Actions | Versioned guide · Declarative guide |
| GitLab CI | Versioned guide · Declarative guide |
| CircleCI | Versioned guide · Declarative guide |
| Bitbucket Pipes | Versioned guide · Declarative guide |
| Azure DevOps | GitHub repos · Azure repos |
| Terraform Provider | atlasgo.io/integrations/terraform-provider |
| Kubernetes Operator | atlasgo.io/integrations/kubernetes |
| ArgoCD | atlasgo.io/guides/deploying/k8s-argo |
| Flux | atlasgo.io/guides/deploying/k8s-flux |
| Crossplane | atlasgo.io/guides/deploying/crossplane |
| Go SDK | pkg.go.dev/ariga.io/atlas-go-sdk/atlasexec |
Atlas provides Agent Skills, an open standard for packaging migration expertise for AI coding assistants: Claude Code, GitHub Copilot, Cursor, OpenAI Codex. Learn more at AI tools docs.
schema inspectEasily inspect your database schema by providing a database URL and convert it to HCL, JSON, SQL, ERD, or other formats.
Inspect a specific MySQL schema and get its representation in Atlas DDL syntax:
atlas schema inspect -u "mysql://root:pass@localhost:3306/example" > schema.hcl
Result
table "users" {
schema = schema.example
column "id" {
null = false
type = int
}
...
}
Inspect the entire MySQL database and get its JSON representation:
atlas schema inspect \
--url "mysql://root:pass@localhost:3306/" \
--format '{{ json . }}' | jq
Result
{
"schemas": [
{
"name": "example",
"tables": [
{
"name": "users",
"columns": [
...
]
}
]
}
]
}
Inspect a specific PostgreSQL schema and get its ERD representation in Mermaid syntax:
atlas schema inspect \
--url "postgres://root:pass@:5432/test?search_path=public&sslmode=disable" \
--format '{{ mermaid . }}'
erDiagram
users {
int id PK
varchar name
}
blog_posts {
int id PK
varchar title
text body
int author_id FK
}
blog_posts }o--o| users : author_fk
Use the split format for one-file-per-object output:
atlas schema inspect -u '<url>' --format '{{ sql . | split | write }}'
├── schemas
│ └── public
│ ├── public.sql
│ ├── tables
│ │ ├── profiles.sql
│ │ └── users.sql
│ ├── functions
│ └── types
└── main.sql
schema diffCompare two schema states and get a migration plan to transform one into the other. A state can be specified using a database URL, HCL, SQL, or ORM schema, or a migration directory.
atlas schema diff \
--from "postgres://postgres:pass@:5432/test?search_path=public&sslmode=disable" \
--to file://schema.hcl \
--dev-url "docker://postgres/15/test"
$ claude mcp add atlas \
-- python -m otcore.mcp_server <graph>