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-migrateSetting 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 initThis 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 upgradeThis 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 versionRolling 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 migrationsCommon Migration Operations
| Operation | Generated SQL |
|---|---|
| Add column | ALTER TABLE ... ADD COLUMN ... |
| Drop column | ALTER TABLE ... DROP COLUMN ... |
| Rename column | ALTER TABLE ... RENAME COLUMN ... |
| Add table | CREATE TABLE ... |
| Drop table | DROP TABLE ... |
| Add index | CREATE 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.
