Dependency Tracking¶
Declaring Dependencies¶
Migrations declare dependencies via depends_on:
class LoadPerson(DataMigration):
revision = "D002"
depends_on = ["D001"] # D001 must be applied first
Delembic builds a directed acyclic graph (DAG) and runs migrations in topological order. File names and filesystem order are irrelevant.
Dependency Shapes¶
Linear chain¶
D001 → D002 → D003
class D002(DataMigration):
revision = "D002"
depends_on = ["D001"]
class D003(DataMigration):
revision = "D003"
depends_on = ["D002"]
Diamond (fan-out / fan-in)¶
D001
/ \
D002 D003
\ /
D004
class D002(DataMigration):
revision = "D002"
depends_on = ["D001"]
class D003(DataMigration):
revision = "D003"
depends_on = ["D001"]
class D004(DataMigration):
revision = "D004"
depends_on = ["D002", "D003"]
D002 and D003 can run in either order (both depend on D001). D004 runs last.
Independent migrations¶
class D001(DataMigration):
revision = "D001"
depends_on = []
class D002(DataMigration):
revision = "D002"
depends_on = []
When no dependency exists between two migrations, Delembic runs them in the order it encounters them (stable sort).
External Dependencies (Alembic Revisions)¶
depends_on can reference Alembic schema migration IDs:
class LoadPerson(DataMigration):
revision = "D001"
depends_on = ["3d1e3e6abc12"] # Alembic revision
Delembic identifies external deps as any entry in depends_on that is not a known Delembic revision. At upgrade time, it verifies those Alembic revisions are applied before running the migration.
See Alembic Integration for full details.
Cycle Detection¶
Cycles raise CycleError at upgrade time:
# This will fail at runtime
class D001(DataMigration):
revision = "D001"
depends_on = ["D002"] # D001 depends on D002...
class D002(DataMigration):
revision = "D002"
depends_on = ["D001"] # ...and D002 depends on D001 → cycle
delembic.dag.CycleError: Cycle detected involving: D001, D002
Target Upgrades¶
Run up to a specific revision instead of head:
delembic upgrade D003
Delembic runs all pending migrations that are ancestors of D003 (including D003 itself), in dependency order. Migrations after D003 in the DAG are skipped.
How the DAG Works¶
Delembic uses Kahn’s algorithm for topological sort:
Build in-degree count for each migration
Start with zero-in-degree nodes (no dependencies)
Process queue: emit node, decrement in-degrees of dependents, enqueue new zeros
If any nodes remain after processing → cycle detected
External dependencies (Alembic revisions, or any ID not in the migrations dict) are silently excluded from the in-degree calculation — they don’t block topological sort, only runtime checks verify them.