Alembic autogenerate pitfalls and creating indexes CONCURRENTLY

Backend Live Coding November 13, 2026 python

Autogenerate is a suggestion, not a final file.

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# ======================================================================
# Q: How do you work with Alembic? What do you watch for in autogenerate?
#
# Autogenerate is a suggestion, not a final file. It does not always detect a
# rename (it sees it as drop + add, so you lose data), changes to server
# defaults, or some constraints. I read every migration before committing. For
# large tables I do the same as in Django: expand/contract, index CONCURRENTLY,
# backfill in batches.
# In CI I run alembic upgrade head on an empty database and check that
# autogenerate produces no new changes (the model and the database agree). I do
# the same in Django with makemigrations --check.
# ======================================================================

def upgrade():
    # CONCURRENTLY cannot run inside a transaction
    with op.get_context().autocommit_block():
        op.create_index('ix_events_created_at', 'events', ['created_at'],
                        postgresql_concurrently=True)

def downgrade():
    with op.get_context().autocommit_block():
        op.drop_index('ix_events_created_at', table_name='events',
                      postgresql_concurrently=True)