Flask Migrations

A database migration is a controlled change to your database schema — adding a column, renaming a table, or changing a data type — without deleting existing data. Flask-Migrate handles migrations for SQLAlchemy databases and keeps a full history of every schema change.

Why Migrations Matter

Calling db.create_all() creates tables if they do not exist. It does nothing to tables that already exist. If you add a column to a model after the table exists, db.create_all() silently ignores it. Migrations detect the difference between your models and the actual database and generate SQL to close the gap.

Model definition:  id, name, email, phone  (phone is new)
Actual database:   id, name, email

Migration detects: phone column is missing
Migration adds:    ALTER TABLE user ADD COLUMN phone VARCHAR(20)

Installing Flask-Migrate

pip install flask-migrate

Setting Up Flask-Migrate

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///myapp.db'

db = SQLAlchemy(app)
migrate = Migrate(app, db)

The Migration Workflow

Step 1: flask db init       (run once — creates migrations/ folder)
Step 2: flask db migrate    (generates a migration file from model changes)
Step 3: flask db upgrade    (applies the migration to the database)

Step 1: Initialize the Migrations Folder

flask db init

This creates a migrations/ folder in your project. Run this only once per project. The folder stores the migration history and configuration.

Step 2: Generate a Migration

flask db migrate -m "add phone column to user"

Flask-Migrate compares your current models with the database schema and generates a migration script inside migrations/versions/. The -m flag adds a human-readable message to identify the migration.

A generated migration file looks like:

def upgrade():
    op.add_column('user', sa.Column('phone', sa.String(length=20), nullable=True))

def downgrade():
    op.drop_column('user', 'phone')

Every migration has an upgrade() function (applies the change) and a downgrade() function (reverses it). Always review the generated file before applying it to production.

Step 3: Apply the Migration

flask db upgrade

This runs the upgrade() function and updates the actual database. Flask-Migrate records which migrations have run in a special alembic_version table so it never runs the same migration twice.

Viewing Migration History

flask db history    # shows all migrations
flask db current    # shows the current database version

Rolling Back a Migration

flask db downgrade    # rolls back the last migration
flask db downgrade -1 # same as above
flask db downgrade base # rolls back all migrations

Common Migration Operations

OperationGenerated SQL
Add columnALTER TABLE ... ADD COLUMN ...
Drop columnALTER TABLE ... DROP COLUMN ...
Rename columnALTER TABLE ... RENAME COLUMN ...
Add tableCREATE TABLE ...
Drop tableDROP TABLE ...
Add indexCREATE INDEX ...

Project Structure After Init

myapp/
├── app.py
├── migrations/
│   ├── alembic.ini
│   ├── env.py
│   ├── script.py.mako
│   └── versions/
│       ├── 001_initial_tables.py
│       └── 002_add_phone_column.py

Summary

Flask-Migrate tracks and applies database schema changes without destroying existing data. Initialize once with flask db init. After every model change, run flask db migrate to generate a migration script, review it, then run flask db upgrade to apply it. Commit migration files to version control so every developer and every deployment stays in sync with the same schema.

Leave a Comment

Your email address will not be published. Required fields are marked *