Flyway Undo Alternative in Atlas
Flyway's undo
feature allows you to revert applied migrations by running manually written undo scripts.
While this sounds useful in theory, in practice these pre-written undo (down) files come with significant limitations: they must be
written before the migration is applied, they assume the migration succeeded fully, and they're rarely tested in production scenarios.
Atlas takes a fundamentally different approach with its migrate down
command. Instead of requiring pre-written undo files,
Atlas computes rollback plans dynamically based on the actual state of your database. This means Atlas can handle partial
failures, work across non-transactional DDL operations, and provide built-in safety checks - all automatically.
Quick Comparison
Capability | Flyway Undo | Atlas Migrate Down |
---|---|---|
Auto-generated undo scripts | ✅ Enterprise only (via Flyway Desktop / Redgate Compare) | ✅ Always, computed dynamically |
Requires manual undo files | Yes | No |
Works after partial/failed migration | ❌ No | ✅ Yes |
Handles non-transactional DDL | ⚠️ Limited | ✅ Yes |
Built-in safety checks | ⚠️ Manual | ✅ Automatic |
CI/CD friendly | ⚠️ Limited | ✅ Fully supported |
Available in free tier | ❌ No | ✅ Yes |
The Problem with Pre-written Undo (Down) Scripts
They Assume Perfect Success
Flyway's undo files are written before you know whether the migration will succeed. Consider this scenario:
ALTER TABLE users ADD COLUMN email VARCHAR(255);
ALTER TABLE users ADD COLUMN phone VARCHAR(50);
The corresponding undo file would be:
ALTER TABLE users DROP COLUMN phone;
ALTER TABLE users DROP COLUMN email;
But what if the migration fails after adding email
but before adding phone
? Running the undo script will fail because
phone
doesn't exist. Your database is now in an unknown state, and you need manual intervention to fix it.
Production Usage Limitations
Undo files are rarely used in production as-is, if ever. Teams often maintain thousands of them "just in case," but when failures occur, these files either don't work (due to partial application) or cause data loss that teams aren't willing to accept.
As detailed in our blog post The Myth of Down Migrations, even teams at companies like Meta with thousands of down files, they were virtually never used in production environments.
Incompatible with CD/GitOps Workflows
CD/GitOps workflows assume you can roll back to any previous version by deploying artifacts from an earlier commit. But those earlier commits don't contain the undo files needed to revert database changes - those files only exist in future commits.
This creates a mismatch between application rollbacks and database rollbacks, forcing teams to handle database reversions manually.
How Atlas Migrate Down Works
Atlas's migrate down
command computes rollback plans based on your database's actual current state. Here's what makes it different:
State-Aware Planning
Instead of pre-written scripts, Atlas:
- Inspects your current database state
- Determines what migrations were applied (fully or partially)
- Computes the exact sequence of statements needed to reach the target version
- Validates the plan with automatic safety checks, and follows your team policies
Partial Failure Handling
For databases that support transactional DDLs (like PostgreSQL), Atlas wraps the entire rollback in a transaction. If anything fails, the database returns to its pre-rollback state.
For databases without transactional DDL support (like MySQL), Atlas reverts changes statement-by-statement, updating the revisions table after each successful step. If a failure occurs midway, you can simply re-run Atlas to continue from where it stopped.
Built-in Safety Checks
By default, Atlas runs pre-migration checks before executing any rollback. For example, before dropping a column, Atlas verifies that it contains no data:
-- checks before reverting version 20240305171146
-> SELECT NOT EXISTS (SELECT 1 FROM `logs`) AS `is_empty`
-- ok (50.472µs)
-- reverting version 20240305171146
-> DROP TABLE `logs`
-- ok (53.245µs)
If the check fails, the rollback is aborted, preventing unintended data loss.
Basic Usage
Reverting the Last Migration
To revert the most recently applied migration:
- MySQL
- PostgreSQL
- SQLite
atlas migrate down \
--dir "file://migrations" \
--url "mysql://root:pass@localhost:3306/example" \
--dev-url "docker://mysql/8/dev"
atlas migrate down \
--dir "file://migrations" \
--url "postgres://postgres:pass@:5432/example?search_path=public&sslmode=disable" \
--dev-url "docker://postgres/15/dev?search_path=public"
atlas migrate down \
--dir "file://migrations" \
--url "sqlite://file.db" \
--dev-url "sqlite://dev?mode=memory"
Reverting Multiple Migrations
To revert a specific number of migrations:
atlas migrate down 3 \
--dir "file://migrations" \
--url "mysql://root:pass@localhost:3306/example" \
--dev-url "docker://mysql/8/dev"
Reverting to a Specific Version
To roll back to a particular version:
atlas migrate down \
--to-version 20240301000000 \
--dir "file://migrations" \
--url "mysql://root:pass@localhost:3306/example" \
--dev-url "docker://mysql/8/dev"
Reverting to a Git Tag
If you're using Atlas Cloud's Schema Registry, you can tag migration directory states and revert to those tags:
atlas migrate down \
--to-tag "v1.2.0" \
--dir "file://migrations" \
--url "mysql://root:pass@localhost:3306/example" \
--dev-url "docker://mysql/8/dev"
Production Safety Features
Dry Run Mode
Preview what Atlas will do without executing any changes:
atlas migrate down --dry-run \
--dir "file://migrations" \
--url "mysql://root:pass@localhost:3306/example" \
--dev-url "docker://mysql/8/dev"
This shows the exact SQL statements that will be executed and which safety checks will run.
Approval Workflows
For production environments, Atlas Cloud supports approval workflows. When a migrate down
operation is triggered
(via CLI or GitHub Actions), it can be configured to wait for approval from designated reviewers before execution.
This ensures that potentially destructive operations are reviewed by multiple team members before being applied.
CI/CD Integration
GitHub Actions
Atlas provides a dedicated GitHub Action for migrate down operations. This allows you to:
- Connect your migration directory to the Schema Registry
- Set up a workflow that can be triggered on-demand or by tagging a commit
- Require approval before execution
- Apply the rollback once approved
name: Rollback Database
on:
workflow_dispatch:
inputs:
tag:
description: 'Migration tag to roll back to'
required: true
jobs:
rollback:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ariga/atlas-action/migrate/down@v1
with:
url: ${{ secrets.DATABASE_URL }}
to-tag: ${{ github.event.inputs.tag }}
dir: migrations
See the Atlas Down Action documentation for details.
Comparison with Flyway Workflows
Flyway Undo Workflow
- Write your migration file:
V001__add_table.sql
- Write the corresponding undo file:
U001__add_table.sql
- Test the undo file separately (often skipped)
- Apply migration:
flyway migrate
- If rollback needed:
flyway undo
(Teams/Enterprise only) - Undo file assumes full success
Limitations:
- Undo files must be written manually for every migration
- No automatic safety checks
- Doesn't handle partial failures
- Undo feature requires Enterprise license
- Rarely tested in production-like environments
Atlas Migrate Down Workflow
- Define your desired schema in code (HCL, SQL, or ORM)
- Generate migration:
atlas migrate diff
- Apply migration:
atlas migrate apply
- If rollback needed:
atlas migrate down
- Atlas automatically computes the rollback based on database current state
Features:
- No need for manual undo (down) files to maintain
- Automatic safety checks prevent data loss
- Handles partial failures gracefully
- Works in both free and paid tiers
- Integrates with approval workflows for production environments
Use Cases
Local Development
Iterate on schema changes without manually writing undo (down) scripts:
# Try a schema change
atlas migrate diff --edit
# Apply it
atlas migrate apply --env local
# Changed your mind? Revert it
atlas migrate down --env local
# Delete the migration file
atlas migrate rm 20240305171146
Staging/Test Environment Resets
Reset a test environment to a specific schema version for testing:
atlas migrate down --to-version 20240301000000 --env staging
Production Rollbacks
Roll back a production deployment that introduced database issues:
# Preview the rollback
atlas migrate down --dry-run --env production
# Execute with approval (via Atlas Cloud)
atlas migrate down --env production
Migration from Flyway
If you're currently using Flyway with undo files, migrating to Atlas is straightforward:
-
Import your existing migrations using Atlas migration import:
atlas migrate import \
--from "file://migrations?format=flyway" \
--to "file://atlas-migrations"Note: Undo files (
U__
prefix) are not imported because Atlas computes them dynamically. -
Test migrate down on a development database:
atlas migrate down --env dev
-
Remove undo files from your repository - they're no longer needed!
For a complete migration guide, see Migrating from Flyway to Atlas.
Summary
Atlas's migrate down
command provides an alternative to Flyway's undo scripts by:
- Computing rollback plans dynamically based on current database state
- Handling partial migration failures automatically
- Running safety checks before executing destructive operations
- Supporting both transactional and non-transactional DDL databases
- Integrating with approval workflows and CI/CD pipelines
- Working with GitOps workflows through version tagging