Skip to content

Changing the Database Schema

Database Setup covers the very first alembic upgrade head against an empty database. This is the loop you’ll actually use — every time a model changes.

Edit app/models.py directly. Item already has a created_at field, defined like this — any new timestamp field you add follows the same shape:

class Item(ItemBase, table=True):
created_at: datetime | None = Field(
default_factory=get_datetime_utc,
sa_type=DateTime(timezone=True),
)
Terminal window
cd backend
uv run alembic revision --autogenerate -m "add created_at to item"

Alembic diffs your models against the database’s current state — app/alembic/env.py points it at SQLModel.metadata — and writes a new file into app/alembic/versions/. A real one looks like this:

def upgrade():
op.add_column('item', sa.Column('created_at', sa.DateTime(timezone=True), nullable=True))
def downgrade():
op.drop_column('item', 'created_at')

Autogenerate is a diff, not a decision-maker — it gets a few things wrong in predictable ways:

Terminal window
uv run alembic upgrade head
Terminal window
uv run alembic downgrade -1

downgrade() is autogenerated too, alongside upgrade() — the same review applies to both before you rely on it.