If you're building a Python app with a database,
you need migrations.
Migrations let you change your database schema
without losing data. Add a column, rename a table,
drop an index — all safely and reversibly.
Alembic is the standard migration tool for
Python + SQLAlchemy apps.
This guide covers everything you need to know.
What is Alembic?
Alembic is a database migration tool for Python.
It works with SQLAlchemy and supports:
- PostgreSQL
- MySQL
- SQLite
- Oracle
- Microsoft SQL Server
Think of it like Git — but for your database schema.
Every change is versioned, reversible, and trackable.
Install Alembic
pip install alembic sqlalchemy
Verify installation:
alembic --version
Project Setup
Create a new project:
alembic init migrations
This creates:
migrations/
env.py
script.py.mako
versions/
alembic.ini
Configure Database URL
Open alembic.ini and set your database URL:
For SQLite (easiest to start):
sqlalchemy.url = sqlite:///myapp.db
For PostgreSQL:
sqlalchemy.url = postgresql://user:password@localhost/dbname
For MySQL:
sqlalchemy.url = mysql+pymysql://user:password@localhost/dbname
Define Your Models
Create models.py:
from sqlalchemy import Column, Integer, String,
DateTime, create_engine
from sqlalchemy.orm import DeclarativeBase
from datetime import datetime
class Base(DeclarativeBase):
pass
class User(Base):
tablename = "users"
id = Column(Integer, primary_key=True)
email = Column(String(255), unique=True)
name = Column(String(100))
created_at = Column(DateTime, default=datetime.utcnow)
Configure env.py
Open migrations/env.py and add your models:
from models import Base
target_metadata = Base.metadata
Create Your First Migration
Auto-generate migration from your models:
alembic revision --autogenerate -m "create users table"
This creates a file in migrations/versions/ like:
2026_07_27_abc123_create_users_table.py
It looks like this:
def upgrade() -> None:
op.create_table('users',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('email', sa.String(255), nullable=True),
sa.Column('name', sa.String(100), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email')
)
def downgrade() -> None:
op.drop_table('users')
Run Migration (Upgrade)
Apply migration to database:
alembic upgrade head
Check current version:
alembic current
View migration history:
alembic history
Add a Column
Add phone field to User model:
phone = Column(String(20), nullable=True)
Generate migration:
alembic revision --autogenerate -m "add phone to users"
Run it:
alembic upgrade head
Rollback Migration (Downgrade)
Undo last migration:
alembic downgrade -1
Undo all migrations:
alembic downgrade base
Go to specific version:
alembic downgrade abc123
Common Alembic Commands
alembic upgrade head # Apply all migrations
alembic downgrade -1 # Undo last migration
alembic current # Show current version
alembic history # Show all migrations
alembic heads # Show latest versions
alembic revision --autogenerate -m "message" # Create migration
Best Practices
Always review auto-generated migrations
before running themNever edit a migration after it's been
run in productionKeep migrations small and focused —
one change per migrationAlways test downgrade() works before
deploying to productionCommit migration files to git — they
are part of your codebase
Common Errors and Fixes
"Target database is not up to date":
alembic upgrade head
"Can't locate revision":
alembic history --verbose
"No changes detected" on autogenerate:
Check env.py imports your models correctly
Practice Alembic in Your Browser
Want to practice SQLAlchemy and database
concepts without setting up a local environment?
Try pyrun.in — SQLite playground and Python
terminal run directly in your browser.
No install. No setup. Just open and code.
Free to start → pyrun.in
Built pyrun.in — browser-based Python learning
in Mumbai. Questions welcome in comments.
Top comments (0)