Skip to main content
Database migrations are SQL statements that create, update, or delete database schemas. They provide a structured way to track and version your database changes over time, making it easy to share schema updates across your team and deploy to production.

Why Use Migrations?

Migrations provide several key benefits:
  • Version control: Track database schema in Git alongside your code
  • Reproducibility: Recreate your database schema at any point in time
  • Team collaboration: Share schema changes easily across developers
  • Safe deployments: Apply tested changes to production systematically
  • Rollback capability: Revert changes if issues arise
  • Environment parity: Keep development, staging, and production in sync

Migration Workflow

Prerequisites

Ensure you have:

Creating Your First Migration

Let’s create a simple employees table to demonstrate the migration workflow.
1

Generate a migration file

Create a new migration with a descriptive name:
This creates a timestamped file in supabase/migrations/:
2

Add SQL to your migration

Open the migration file and add your SQL:
supabase/migrations/20240304120000_create_employees_table.sql
3

Apply the migration

Run the migration against your local database:
You can now view the employees table in Studio at http://localhost:54323.

Modifying Tables

Now let’s add a department column to demonstrate schema evolution:
1

Create a new migration

2

Add ALTER TABLE statement

supabase/migrations/20240304130000_add_department_column.sql
3

Apply the migration

Migration files are applied in chronological order based on their timestamp prefix.

Schema Diffing

If you prefer using the Dashboard or SQL editor to make changes, you can generate migrations from schema differences.

Create Changes in Dashboard

  1. Open Studio at http://localhost:54323
  2. Create a new table called cities with columns:
    • id (bigint, primary key, identity)
    • name (text)
    • population (bigint)

Generate Migration from Diff

Generate a migration file from your changes:
This creates a new migration file with the SQL needed to recreate your changes:
supabase/migrations/20240304140000_create_cities_table.sql

Test Your Migration

Reset your database to test the migration:
This will:
  1. Drop the database
  2. Reapply all migrations in order
  3. Run your seed file (if it exists)
supabase db reset destroys all local data. Always save important changes first:

Migration Best Practices

1. Keep Migrations Atomic

Each migration should focus on a single logical change:

2. Use Idempotent SQL

Make migrations safe to run multiple times:

3. Handle Lock Timeouts

For large tables, set lock timeout to prevent blocking:

4. Always Enable RLS

Enable Row Level Security on new tables:

5. Use Descriptive Names

Name migrations clearly:

Common Migration Patterns

Adding Indexes

Use CONCURRENTLY to avoid locking the table during index creation.

Creating Triggers

Adding Foreign Keys

Creating Functions

Renaming Columns Safely

Seeding Data

Use supabase/seed.sql for development data:
supabase/seed.sql
Apply seed data:
Seed files are for development only. Don’t use them for production data.

Deploying Migrations

First, authenticate and link to your Supabase project:
Select your project from the interactive prompt.

Push Migrations to Production

Deploy your migrations:
This applies all pending migrations to your remote database.

Push with Seed Data (Optional)

For staging environments, you can include seed data:
Never use --include-seed in production as it may overwrite real data.

Migration Commands Reference

Troubleshooting

Error: syntax error at or near...Solution:
  • Validate SQL syntax in a SQL editor
  • Check for missing semicolons
  • Ensure proper quoting of identifiers
  • Test migration locally first: supabase db reset
Error: relation "table_name" already existsSolution:
  • Use CREATE TABLE IF NOT EXISTS
  • Check if migration was already applied
  • Review migration history: supabase migration list
Error: canceling statement due to lock timeoutSolution:
  • Increase lock timeout in migration:
  • Run during low-traffic period
  • Use CONCURRENTLY for index creation
Error: permission denied for schema publicSolution:
  • Ensure you’re using the correct schema
  • Check RLS policies aren’t blocking operations
  • Verify migration uses proper privileges

Advanced Topics

Multi-Stage Deployments

For zero-downtime deployments of breaking changes:
1

Migration 1: Add new column

2

Deploy application update

Update app to write to both columns
3

Migration 2: Backfill data

4

Migration 3: Switch over

Managing Multiple Environments

Use different projects for each environment:

Next Steps

Deploy to Production

Learn how to deploy your project to Supabase Platform

Database Testing

Set up automated testing for your database

CI/CD Integration

Automate migrations with GitHub Actions

CLI Reference

Complete CLI command reference