Shift Left Every Database Change
Ariga builds Atlas, which connects schema changes, permissions, and data operations into a single code-reviewed pipeline that plans, tests, and verifies every change before it reaches production, so engineers, security teams, and coding agents can change databases without breaking them.
Code is abundant. Your data is not.
Customer stories
What teams achieve with Atlas#
From four database admins to 50+ engineers shipping schema changes.
EliseAI's AI platform helps property managers and healthcare providers handle leasing, maintenance, and resident engagement. Engineers change the schema in a pull request, and Atlas generates the migration, lints it, and reports the result on the PR.
“We haven't had any database locking or migration issues since we've rolled out Atlas.”
Compliance audits in hours, not weeks. Releases without the 45-minute backup.
Health in Tech automates self-funded health insurance plans for small and medium-sized businesses. Atlas Cloud records who applied each migration, to which database, and the SQL Atlas generated, which the team pulls as audit evidence on demand.
“I had to provide evidence about how we manage these things, and I could easily go into Atlas Cloud and pull them out.”
One rulebook for every project's schema.
Aircall, the cloud phone platform for sales and support teams, adopted Atlas as part of a PostgreSQL reliability effort and wrote about it on its engineering blog.
“The tool has been promising so far, helping us manage migrations, detect schema drift, and enforce best practices across projects.”
One platform team, one migration standard for the entire company.
Brazil's leading digital identity provider manages infrastructure as code with Terraform and its database schemas as code with Atlas, instead of changing them by hand.
“Month over month, we see smaller and smaller incidents.”
Every SQL Server change planned and linted in CI before release.
The third-largest seed brand in the US, founded in 1937, replaced its homegrown migration system with Atlas.
“I rely on Atlas because I know it works and it gets the job done.”
Spanner, Aurora, and ClickHouse, one schema workflow.
Gumloop, a platform for building AI agents, chose Atlas over Liquibase and Flyway. Each pull request is checked against staging and production, and coding agents fix failed migrations from the Atlas output.
“The biggest win of any tool is when you don't need to look at it ever again and it just works.”
Unsafe migrations never reach production.
Wenrix, the AI platform leading travel agencies use for air retail, deploys several times a day on Kubernetes. The Atlas Operator stops any deploy with an unsafe migration.
“Atlas just works behind the scenes. We don't need to pay attention to it. We can trust that it's getting the job done.”
Migrations as a Kubernetes resource, applied on every deploy across five environments.
Aryon's preventative cloud security platform runs the Atlas Kubernetes Operator in every environment, from local clusters to two production regions, and no one applies a migration by hand.
“It connects to our models and people don't even have to think about migrations, they just happen.”
More than one migration a day on a schema Flyway and Liquibase could not handle.
Darkhorse builds decision analytics for fire departments on PostgreSQL, where one view can feed 50 others. Atlas plans each change, so developers who avoided the database now change it.
“I don't feel afraid to hit the approve button and pack up and go home for the day.”
Developers change the schema without waiting on the DBA.
Israel's most popular online marketplace uses Atlas so developers propose schema changes in pull requests and the DBA reviews each migration before it reaches production.
“We wanted to have a source of truth in code… Since we use Terraform, we wanted something similar that everybody would already feel comfortable with.”
1,500 tenant schemas on Redshift, kept identical with no drift.
The browser security company gives each customer its own schema on Amazon Redshift, and Atlas applies every migration to all 1,500 of them from one schema file.
“Having a lot of database schemas but only one tool to manage them all makes our lives so much easier.”
Also on Atlas
“Atlas enables our team to efficiently and safely manage our application schema. With features like linting, automated migrations for our ORM, and Kubernetes support, it seamlessly integrates into our development ecosystem.”
“We’ve been using Atlas for >1 year now and we still love it…”
“Generating and applying migrations is very straight-forward. A powerful and elegant tool, we are now integrating Atlas into our GitHub workflows. Atlas is a natural extension of the tools we already use and a joy to work with!”
See Atlas in action
One engine behind every database change#
Atlas plans, simulates, verifies, and records every change, on any database.
Explorer
1table "orders" {2 schema = schema.public3 // ... columns and keys from above ...4 row_security {5 enabled = true // ENABLE ROW LEVEL SECURITY6 enforced = true // FORCE ROW LEVEL SECURITY7 }8}9 10policy "tenant_isolation" {11 on = table.orders12 for = ALL13 to = ["app_writer"]14 using = "(tenant_id = current_setting('app.current_tenant')::integer)"15 check = "(tenant_id = current_setting('app.current_tenant')::integer)"16}
1role "app_readonly" {2 comment = "Read-only access"3}4 5role "app_writer" {6 member_of = [role.app_readonly]7}8 9user "api_service" {10 member_of = [role.app_writer, role.rds_iam]11}12 13user "dashboard" {14 password = var.dash_password15 member_of = [role.app_readonly]16}
1permission {2 for_each = [table.users, table.orders]3 for = each.value4 to = role.app_readonly5 privileges = [SELECT]6}7 8permission {9 for = table.orders10 to = role.app_writer11 privileges = [INSERT, UPDATE]12}13 14permission {15 for = schema.public16 to = role.app_admin17 privileges = [ALL]18}
1script "loop" "purge_deleted" {2 iterator "keyset" {3 cursor {4 id = int5 }6 init {7 sql = "SELECT id FROM users WHERE deleted = 1 AND purged = 0 ORDER BY id LIMIT 100"8 }9 next {10 sql = "SELECT id FROM users WHERE deleted = 1 AND purged = 0 AND id > ? ORDER BY id LIMIT 100"11 args = [cursor.id]12 }13 }14 do {15 http "search" {16 url = "https://search.internal/documents/delete"17 method = POST18 headers = { Content-Type = "application/json" }19 body = jsonencode({ ids = iterator.keyset.batch[*].id })20 expect_status = 20021 }22 // Mark rows purged only after the call succeeds, so a failed23 // batch stays pending and is retried on the next run.24 exec {25 sql = "UPDATE users SET purged = 1 WHERE id IN (SELECT value FROM json_each(?))"26 args = [jsonencode(iterator.keyset.batch[*].id)]27 }28 }29}
❯ add tenant isolation to orders and a reader role for the dashboard
⏺ Update(db/schema.pg.hcl)
⎿ Updated db/schema.pg.hcl (+11 -1)
table "orders" {
schema = schema.public
// ... columns and keys from above ...
row_security {
enabled = true // ENABLE ROW LEVEL SECURITY
enforced = true // FORCE ROW LEVEL SECURITY
}
}
// TODO: isolate tenants with row-level security
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)"
}
⏺ Update(db/access.hcl)
⎿ Updated db/access.hcl (+6 -1)
role "app_readonly" {
comment = "Read-only access"
}
role "app_writer" {
member_of = [role.app_readonly]
}
…
user "dashboard" {
password = var.dash_password
member_of = [role.app_writer]
member_of = [role.app_readonly]
}
⏺ Update(db/permissions.hcl)
⎿ Updated db/permissions.hcl (+7 -1)
permission {
for_each = [table.users, table.orders]
for = each.value
to = role.app_readonly
privileges = [SELECT]
}
permission {
…
permission {
for = schema.public
to = role.app_admin
privileges = [ALL]
grantable = true
}
⏺ Bash(atlas schema apply --env dev --dry-run)
⎿ Planning migration statements (9 in total):
-- create role "app_readonly":
-> CREATE ROLE "app_readonly";
-- grant role "app_readonly" to "app_writer":
-> GRANT "app_readonly" TO "app_writer";
… +15 lines
⏺ Atlas planned 9 statements: a read-only role for the dashboard, SELECT on users and
orders, row-level security on orders, and ALL on public without the grant option.
⏺ Bash(atlas schema apply --env dev)
⎿ Planning migration statements (9 in total):
⏺ Applied to dev. Atlas linted the plan on the dev database and approved it on its own:
the report has no errors, and atlas.hcl sets review = ERROR.
✻ Percolating… (0s · thinking with max effort)
❯
⏵⏵ auto mode on (shift+tab to cycle)
❯ add tenant isolation to orders and a reader role for the dashboard
⏺ Update(db/schema.pg.hcl)
⎿ Updated db/schema.pg.hcl (+11 -1)
table "orders" {
schema = schema.public
// ... columns and keys from above ...
row_security {
enabled = true // ENABLE ROW LEVEL SECURITY
enforced = true // FORCE ROW LEVEL SECURITY
}
}
// TODO: isolate tenants with row-level security
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)"
}
⏺ Update(db/access.hcl)
⎿ Updated db/access.hcl (+6 -1)
role "app_readonly" {
comment = "Read-only access"
}
role "app_writer" {
member_of = [role.app_readonly]
}
…
user "dashboard" {
password = var.dash_password
member_of = [role.app_writer]
member_of = [role.app_readonly]
}
⏺ Update(db/permissions.hcl)
⎿ Updated db/permissions.hcl (+7 -1)
permission {
for_each = [table.users, table.orders]
for = each.value
to = role.app_readonly
privileges = [SELECT]
}
permission {
…
permission {
for = schema.public
to = role.app_admin
privileges = [ALL]
grantable = true
}
⏺ Bash(atlas schema apply --env dev --dry-run)
⎿ Planning migration statements (9 in total):
-- create role "app_readonly":
-> CREATE ROLE "app_readonly";
-- grant role "app_readonly" to "app_writer":
-> GRANT "app_readonly" TO "app_writer";
… +15 lines
⏺ Atlas planned 9 statements: a read-only role for the dashboard, SELECT on users and
orders, row-level security on orders, and ALL on public without the grant option.
⏺ Bash(atlas schema apply --env dev)
⎿ Planning migration statements (9 in total):
⏺ Applied to dev. Atlas linted the plan on the dev database and approved it on its own:
the report has no errors, and atlas.hcl sets review = ERROR.
❯ purge the deleted users from the search index
⏺ Read(scripts/purge_deleted.hcl)
⎿ Read 29 lines
⏺ Bash(atlas script loop --env dev --run '^purge_deleted$')
⎿ Executing script "purge_deleted" (scripts/purge_deleted.hcl:1):
⏺ Done. The loop paged through deleted users in batches of 100, deleted each batch from
search, and marked it purged only after the call succeeded.
❯ check that dev matches the schema
⏺ Bash(atlas schema apply --env dev --dry-run)
⎿ Schemas are synced, no changes to be made.
⏺ dev matches the schema in the repository: nothing to apply.
⎿ Running…
Ariel MashrakiCo-founder, ArigaClaude Code in auto mode, running Atlas30 minutes with one of the Atlas engineers.
Schedule a demofeat: add tenant isolation & reader role #312
atlas migrate lint on dirs/ecommerce/migrations
| Status | Step | Result |
|---|---|---|
| 1 new migration file detected | 20250410131547.sql | |
| ERD and visual diff generated | View Visualization | |
| Simulate on dev database | Passed (23ms) | |
| Analyze 20250410131547.sql5 reports were found in analysis | Destructive changes detectedDS103Data dependent changes detectedMF103Blocking table change detectedPG301Concurrent index violationPG101Vulnerable extensions detectedCVE-2026-2005 | |
| Access changesblast radius | api_service → app_writer →+INSERT, UPDATE on orders | |
| Schema policies | no-superuser, no-grantable passed |
Read the full linting report on Atlas Cloud
Ariel MashrakiCo-founder, Ariga5 passed5 diagnostics30 minutes with one of the Atlas engineers.
Schedule a demoIssues
pg_partman
CVE-2021-33204
access_log
FKY01
pg_ivm
CVE-2023-23554CVE-2023-22847
carol
ROL03
Details
Issues
ROL03Overlapping roles assigned to user
Roles "billing_rw" and "billing_support" assigned to user "carol" grant heavily overlapping privileges (2 shared, 67% overlap)
Suggestion:
Consolidate roles "billing_rw" and "billing_support": merge them or move the shared privileges into a common base role, so user "carol" does not hold overlapping grants
Details
Issues
CVE-2021-33204In the pg_partman (aka PG Partition Manager) extension before 4.5.1 for PostgreSQL, arbitrary…
Suggestion:
Upgrade extension "pg_partman" to version 4.5.1 or later to resolve CVE-2021-33204
Ariel MashrakiCo-founder, Ariga12 objects · 16 relationships30 minutes with one of the Atlas engineers.
Schedule a demoscript "loop" "purge_deleted" { iterator "keyset" { cursor { id = int } init { sql = "SELECT id FROM users WHERE deleted = 1 AND purged = 0 ORDER BY id LIMIT 100" } next { sql = "SELECT id FROM users WHERE deleted = 1 AND purged = 0 AND id > ? ORDER BY id LIMIT 100" args = [cursor.id] } } do { http "search" { url = "https://search.internal/documents/delete" method = POST headers = { Content-Type = "application/json" } body = jsonencode({ ids = iterator.keyset.batch[*].id }) expect_status = 200 } // Mark rows purged only after the call succeeds, so a failed // batch stays pending and is retried on the next run. exec { sql = "UPDATE users SET purged = 1 WHERE id IN (SELECT value FROM json_each(?))" args = [jsonencode(iterator.keyset.batch[*].id)] } }}
Ariel MashrakiCo-founder, Ariga6 scripts30 minutes with one of the Atlas engineers.
Schedule a demo←51541300010Passed
migrate down
- Environment
- production
- Atlas version
- v0.40.0
- Executed by
- github-action-bot
database state does not match expected state at version 20250104202944
+CREATE TABLE "otel_traces" (…)
Ariel MashrakiCo-founder, Ariga2/2 approvals · 1 check · 1 statement30 minutes with one of the Atlas engineers.
Schedule a demo←8589952841Passed
migrate push
- Changes
- +3 ~1 -2
- noamcattan
- Pushed 29 days ago
- Branch
- master
- Commit
- 8db35cc
1 table removed · 1 table modified · 1 column added · 2 indexes added · 1 index removed
Deployment Trace
Ariel MashrakiCo-founder, Ariga3 environments30 minutes with one of the Atlas engineers.
Schedule a demoOpen-source leaders in database infrastructure#
Ariga co-founder Ariel Mashraki created Ent at Meta. Ent is now a Linux Foundation project with more than 17,000 GitHub stars.
Ariga is an engineering-first company. Its database and infrastructure engineers and open-source maintainers build and operate Atlas.
Google, Meta, NVIDIA, Intel, and SAP use our open source, and customers in more than 60 countries run Atlas.
Talks and demos on YouTube ↗Board, investors, and advisors
Rona SegevBoard memberCo-founder of TLV Partners
Armon DadgarAdvisorCo-founder of HashiCorp
Guy PodjarnyAngel investorFounder of Snyk and Tessl
Investor
InvestorEngineering-first
Ariga is led by the engineers who write its code.#
Ariel MashrakiFounder and CEOCreated Ent at MetaWorks on Atlas, Ent, and Ent contrib. Contributed to Go, Kubernetes, and PostGIS.
a8m3,090 commits
Rotem TamirCo-founder and advisorWorks on Atlas, Ent, and the Atlas Operator.
rotemtam681 commits
Jannik ClausenHead of EuropeFounding EngineerWorks on Atlas, Ent, and the Atlas GitHub Action.
masseelch425 commits
Giau Tran MinhHead of AsiaFounding EngineerWorks on Atlas, the Atlas Operator, and the Atlas GitHub Action.
giautm765 commitsDat DaoSenior Team Lead
Works on the Atlas Operator, the Atlas GitHub Action, and Atlas.
datdao159 commits
Noam CattanSenior Team LeadWorks on Atlas, the Atlas Operator, and the Atlas GitHub Action.
noamcattan87 commits- Join the teamAcross the US, Israel, Germany, and Vietnam
Hiring in New York, Tel Aviv, Ho Chi Minh City, and Europe (remote).
Our open source is used by
- DatabricksExpanded Object Attribute CoverageThe Databricks driver now covers a much wider set of attributes across schemas, tables, views, materialized views, functions, procedures, and permissions.
- Kubernetes OperatorDev Database Pod MetadataAtlasSchema and AtlasMigration accept a devDB.metadata block that sets labels and annotations on the dev database pod the operator creates.
- SpannerColumn-Level Locality GroupsSpanner columns can now declare their own locality group in an options block, overriding their table's, and Atlas plans the SET OPTIONS statements that move a column between groups.
- OracleColumn CollationsOracle character columns now take a collate attribute, and Atlas plans the MODIFY ... COLLATE statements that add, change, or reset it.
- AzureMicrosoft Entra Token Data SourceThe new azure_db_token data source mints a short-lived Microsoft Entra access token for Azure Database for PostgreSQL and MySQL from inside the project file, so the connection URL no longer carries a static password.
- DACPAC for PostgreSQL: Where Atlas Fills the Gap
Noa RogoszinskiDACPAC is SQL Server only. - The AI-Native SDLC Playbook Stops at the Database
Ariel MashrakiWhy revert-shaped controls fail for schema changes, and the gates that work. - The Myth of Down Migrations; Introducing Atlas Migrate Down
Ariel MashrakiWhy down migrations are a bad idea, and how Atlas reverts applied migrations safely. - The Hard Truth about GitOps and Database Rollbacks
Rotem TamirWhy down migrations break in GitOps workflows, and how the Kubernetes Operator pattern rolls back safely. - The Missing Chapter in the Platform Engineering Playbook
Rotem TamirWritten for SREDay London 2025: the database chapter that platform engineering playbooks leave out.
WebinarOctopus Deploy
GitOps meets databases: schema management with Codefresh and the Atlas Operator
Length 48:07Webinar · Octopus DeployGitOps meets databases: schema management with Codefresh and the Atlas Operator
Length 5:13Demo · AtlasAtlas Cloud CLI: database context for AI agents
Length 29:09Talk · DevOpsDays Warsaw 2023Schema-as-code: developer platforms and database schema changes
Length 8:06Demo · AtlasDatabase CI/CD pipelines with Argo CD and Atlas
Length 2:49Demo · AtlasBootstrap an Atlas project from an existing PostgreSQL schema
Length 17:53Tutorial · DevOps & AI ToolkitHow to inspect, plan, and migrate database schemas with Atlas










