FastAPI - Beginner to Pro / Project 3.5 - Alembic Data Migration

Alembic Revision Downgrade

🔄 Reverting a Column with Alembic Downgrade

In the previous session, we successfully added a phone_number column to our users table using Alembic.

In this session, we’ll learn how to revert that change if needed—removing a column safely from the database using Alembic’s downgrade functionality.


⚡ Step 1: Open the Revision File

  1. Navigate to the alembic/versions/ directory.

  2. Open the revision file you created for the phone number column. Example:

"""create phone_number col on users table

Revision ID: 4297e826229f
Revises: 85d264a3f618
Create Date: 2026-03-13 20:46:27.165628

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision: str = '4297e826229f'
down_revision: Union[str, Sequence[str], None] = '85d264a3f618'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None

def upgrade() -> None:
    op.add_column(
        'users',
        sa.Column('phone_number', sa.String(), nullable=True)
    )

def downgrade() -> None:
    """Downgrade schema."""
    pass

🛠️ Step 2: Add the Downgrade Function

  1. Locate the downgrade() function in the file.

  2. Modify it to drop the column:

def downgrade() -> None:
    op.drop_column('users', 'phone_number')
  • users → name of the table.

  • 'phone_number' → name of the column to remove.

  • This will safely revert the last migration without affecting other columns or data.


🏁 Step 3: Run the Downgrade

Execute the following command in your terminal:

alembic downgrade -1
  • downgrade → tells Alembic to run the downgrade function.

  • 1 → reverts the last applied migration.

✅ Once run, the phone_number column is removed from the users table.


⚠️ Step 4: Update Your Models

After running a downgrade, your SQLAlchemy model should reflect the changes.

  • Remove the phone_number column from models.py if you no longer plan to use it:

class Users(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True, index=True)
    email = Column(String, unique=True)
    username = Column(String, unique=True)
    first_name = Column(String)
    last_name = Column(String)
    hashed_password = Column(String)
    is_active = Column(Boolean, default=True)
    role = Column(String)
    # phone_number = Column(String)  <-- Remove or comment out

If you leave it in the model, FastAPI queries for this column will fail since it no longer exists in the database.


⚡ Step 5: Test the Application

  1. Start the FastAPI application:

uvicorn main:app --reload
  1. You should now see the phone column has been removed, confirming the downgrade was successful.

ezgif-53256f5f157e4443.mp4


❓When to Use Alembic vs SQLAlchemy

  • Alembic → Enhances existing tables without affecting current data. Use for adding/removing columns, modifying constraints.

  • SQLAlchemy → Creates new tables automatically if they don’t exist yet.

Alembic is mainly for database evolution, while SQLAlchemy handles initial table creation.