Skip to main content

Reporting schema migrations to Atlas Cloud

Deploying without Atlas Cloud

A common way to deploy migrations using Atlas (or any other migration tool) is similar to this:

  • When changes are merged to the main branch, a CI/CD pipeline is triggered.
  • The pipeline builds an artifact (usually a Docker image) that includes the migration directory content and Atlas itself.
  • The artifact is pushed to a registry.
  • The deployment process is configured to use this newly created image to run the migrations against the production database.

This process is a common practice, but it requires setting up a CI/CD pipeline (including storage, permissions, and other glue) for each service, adding another layer of complexity.

Why use the Atlas Registry?

The Atlas Registry gives you a single source of truth for the schemas and migration directories of all your services, for both versioned (migrate apply) and declarative (schema apply) workflows. After connecting a migration directory or schema, it is automatically synced to the Registry on every commit to your main branch.

This takes less than one minute to set up. Once it's complete, your deployments – whether run with a single command or through popular CD tools such as Kubernetes and Terraform – read the schema or migration directory from the Registry, apply it to the target database, and report the result back to the Registry.

Reporting deployments unlocks:

Report Migrations to Atlas Cloud

To read the migration directory from the Atlas Registry, use the atlas:// scheme in the migration URL as follows:

atlas.hcl
env {
// Set environment name dynamically based on --env value.
name = atlas.env
migration {
// In this example, the directory is named "myapp".
dir = "atlas://myapp"
}
}

Now you can execute schema migrations and report their result to Atlas Cloud using the following command:

export ATLAS_TOKEN="<ATLAS_TOKEN>"
atlas migrate apply \
--url "<DATABASE_URL>" \
--config file://path/to/atlas.hcl \
--env prod
Deploy a Specific Migration Tag

If you set up CI for your project to push the migration directory to Atlas Cloud, you can deploy a specific migration tag by setting the tag query string in the directory URL. For example:

# Short SHA-1 hash.
--dir "atlas://myapp?tag=267b9d1"

# Full tag.
--dir "atlas://myapp?tag=267b9d1799a3f37ccc0c4112d33f6b3455b62de8"

Screenshot of the Atlas Cloud UI showing a list of migration directory tags with their corresponding commit hashes.

Reporting from a local or templated directory

The examples above report deployments by pointing the migration directory to the Atlas Registry (dir = "atlas://myapp"). Some CI/CD setups can't do this, most commonly when the directory is rendered at deploy time from a template to inject environment-specific or sensitive values. In these cases, use the template_dir data source:

atlas.hcl
data "template_dir" "migrations" {
path = "migrations"
vars = {
schema = var.schema_name
}
}

env {
name = atlas.env
migration {
dir = data.template_dir.migrations.url
}
}

By default, deployments from a local (file://) or data-source directory are not reported to Atlas Cloud. To enable reporting, link the directory to a Registry repository with a repo block and set report = true:

atlas.hcl
env {
name = atlas.env
migration {
dir = data.template_dir.migrations.url // or "file://migrations"
report = true
repo {
name = "myapp"
}
}
}

With this config, atlas migrate apply reports each deployment to Atlas Cloud under the myapp repository - the same deployment record you get from an atlas:// directory - without uploading or pushing the directory itself.

Sensitive data

Reporting sends each applied file's contents to Atlas Cloud, where they appear in the deployment record. Atlas masks SQL string literals with a (sensitive) placeholder by default, but if your directory injects runtime variables or secrets into the SQL (for example via template_dir), mark the affected files or statements with the -- atlas:sensitive directive so their values are redacted before they leave your environment. Alternatively, don't report those migrations at all by omitting report or setting skip_report.

The migration.report attribute

  • report only applies to local and data-source directories. Since atlas:// directories are reported by default, setting report on them has no effect. Use skip_report to turn reporting off instead.
  • report and skip_report are mutually exclusive.
  • Setting report = true without a repo block fails with migration.report requires migration.repo.name to be set.

Skipping Cloud Reporting

When running migrate apply or schema apply with Atlas Registry repositories, migrations are automatically reported to Atlas Cloud. For temporary environments like PR previews or test databases, this creates noise in your deployment history.

You can disable cloud reporting by setting skip_report = true in the migration block:

atlas.hcl
env "preview" {
migration {
dir = "atlas://myapp"
skip_report = true
}
}

Alternatively, use an expression to skip reporting for all environments except specific ones:

atlas.hcl
env {
name = atlas.env
migration {
dir = "atlas://myapp"
skip_report = !contains(["prod", "staging"], atlas.env)
}
}

Visualizing Migration Runs

Schema migrations are an integral part of application deployments, yet the setup might vary between different applications and teams. Some teams may prefer using init-containers, while others run migrations from a structured CD pipeline. There are also those who opt for Helm upgrade hooks or use our Kubernetes operator. The differences also apply to databases. Some applications work with one database, while others manage multiple databases, often seen in multi-tenant applications.

However, across all these scenarios, there's a shared need for a single place to view and track the progress of executed schema migrations. This includes triggering alerts and providing the means to troubleshoot and manage recovery if problems arise.

When you use the configuration above with a valid token, Atlas will log migration runs in your cloud account. Here's a demonstration of how it looks in action:

Inspecting Deployments from the CLI

Beyond the Atlas Cloud UI, you can inspect your databases and their deployment history directly from the CLI using the atlas cloud database and atlas cloud migration commands.

Databases

A database is a deployment target with a current version and sync status (SYNCED, PENDING, or FAILED). List the databases reported to the Registry, optionally filtering by environment:

atlas cloud database list --env-name production
ID   NAME                 ENV         STATUS   CURRENT VERSION
1 prod production SYNCED 20260514083000
2 prod-eu production PENDING 20260512141500
3 staging staging FAILED 20260515093000
--------------------------------
Page: 1 Page Size: 6 Total: 18

Use atlas cloud database describe to view a single database by --id or --ext-id:

atlas cloud database describe --id 1
ID                    1
Name prod
Environment production
Status SYNCED
Current Version 20260514083000
Last Deployment Time 2026-05-14T08:30:00Z

Deployment Events

Each migrate apply or schema apply reported to the Registry is recorded as a deployment event with a status: PASSED, FAILED, NO_ACTION (already up-to-date), or DRY_RUN. List them, filtering by repository, status, environment, or database name:

atlas cloud migration list --repo payments --status PASSED
ID   REPO       TYPE                 ENV         DATABASE    TARGETS  VERSION         STATUS
101 payments MIGRATION_DIRECTORY production prod - 20260514083000 PASSED
102 payments MIGRATION_DIRECTORY production (multiple) 8/8 20260514083000 PASSED
--------------------------------
Page: 1 Page Size: 6 Total: 18

Events that target multiple databases (for example, multi-tenant deployments) show (multiple) and a succeeded/total ratio under TARGETS. View a single event by --id:

atlas cloud migration describe --id 102
ID            102
Repository payments
Type MIGRATION_DIRECTORY
Database (multiple)
Version 20260514083000
Status PASSED
Completed At 2026-05-14T08:35:00Z
Targets 8/8 succeeded
Output formats

Every atlas cloud command accepts a --format flag that takes a Go template to shape the output (for example, emitting JSON with --format '{{ json . }}'). List commands are paginated via --page. See the CLI reference for the full set of flags.