Skip to main content

Why use Atlas with your ORM?

schema-migration-tool

ORMs typically ship with schema management tools. Without a way to provision the database schema, the ORM cannot operate, and so any ORM needs to ship something in order to provide a working developer experience.

Atlas is a language-agnostic schema management tool that can be used to replace the built-in migration tools that ship with popular ORMs like GORM, SQLAlchemy, and Prisma. This document reviews scenarios where you might prefer Atlas over your ORM's built-in tool.

Why ORMs Build Migration Tools

ORMs exist to abstract the DB away and give a more or less equivalent experience across databases (e.g should work more or less the same for PostgreSQL, MySQL, SQL Server, etc.) As an abstraction layer, they tend to focus on the common DB features (tables, indexes, and columns, for example) and not the more advanced features that are specific to a particular database.

Being ORM maintainers ourselves (the team behind Atlas maintains Ent), we can attest that in our capacity as ORM authors, migrations are seen as a "necessary evil", something we have to ship, but really is just an annoying requirement. ORMs exist to bridge code and DB - they are a runtime effort, not a CI/CD or resource management concern.

As such, ORM migration tools tend to be basic and be suitable for such circumstances. In projects that require a more involved schema management process, you might want to consider using a specialized tool like Atlas.

When to use Atlas with your ORM?

Consider using Atlas with your ORM in the following scenarios:

Automatic migration planning

Many ORMs require you to write schema migrations yourself. This is a manual process that can be error-prone and time-consuming. Atlas can automatically plan migrations for you, by loading the desired schema state from your codebase and comparing it to the current state of the database.

Atlas support both a declarative, Terraform-like workflow and a classic versioned migration workflow. In both cases Atlas can automatically plan the migration for you.

If your team can benefit from the automatic planning of migrations, Atlas might be a good fit for your project.

Advanced database features

Notably, some ORMs (such as Prisma and Django) support automatic migrations, but they are usually limited to the diffing of tables, columns, and indexes. Atlas supports more advanced database features, such as views, materialized views, triggers, and stored procedures, as well as extensions and domain types (in PostgreSQL). For a full list of supported features, see the Atlas documentation.

As such, even if your ORM supports automatic migrations, you might still want to use Atlas to manage more advanced database features and better utilize your database's capabilities.

Building a Platform

Platform teams typically need to support teams building applications in a diverse set of languages and frameworks and against a wide range of databases. In such cases, it is useful to have a single tool that can be used across all projects, regardless of the language or framework being used.

Additionally, if you need to ensure that your database schema changes are tested and linted before they are applied to production or want to natively integrate migrations into your CD machinery (e.g. Kubernetes, Terraform, GitHub Actions, ArgoCD, FluxCD, etc.), it is useful to choose a tool that has all of these features built-in.

How Atlas Works with ORMs

Atlas allows loading the desired state of the database schema from external programs or ORMs, regardless of the programing language they are written in. Once the schema is loaded, it can be used by the various Atlas commands such as atlas schema and atlas migrate.

In order to load an external schema, you need first to create an atlas.hcl config file, if you don't already have one and declare a new data source of type external_schema that can be used later as the desired state. Let's explain this with an example.

Given the following atlas.hcl file:

atlas.hcl
data "external_schema" "orm" {
# The first argument is the command to run,
# and the rest are optional arguments.
program = [
"npm",
"run",
"generate-schema"
]
}

env "orm" {
src = data.external_schema.orm.url
dev = "docker://mysql/8/dev"
}

Let's explain what is happening when running atlas with the --env orm command:

  1. The external_schema.orm data source is loaded, by running the command npm run generate-schema and capturing its output as the desired state of the schema.
  2. The program output should be defined as a list of SQL DDL statements separated by semicolon (;) or a custom delimiter. More info about the format can be found in the SQL schema page. For example:
    CREATE TABLE users (id int PRIMARY KEY, name text NOT NULL);

    CREATE TABLE posts (id int PRIMARY KEY, content text NOT NULL, author_id int NOT NULL REFERENCES users(id));
  3. After the schema is loaded, Atlas utilizes the dev-database to parse and validate the SQL definition and converts them into its internal graph representation.
  4. The loaded schema can be used by the various Atlas commands. For example:
    # Generating a new migration.
    atlas migrate diff --env orm
    # Applying the schema to the database.
    atlas schema apply --env orm

Conclusion

Atlas is a powerful schema management tool that can be used to replace the built-in migration tools that ship with popular ORMs. It can be used to manage more advanced database features, automatically plan migrations, and build a platform that supports teams building applications in a diverse set of languages and frameworks.