Problem
We run a high-velocity monorepo where multiple teams land migrations concurrently. In our merge queue, when two PRs each add a migration, the second one to merge discovers there are now two Alembic heads. This kicks the PR out of the merge queue and requires the author to manually rebase and update their migration's down_revision to point at the new head, re-push, and re-enter the queue. With many developers contributing migrations, this compounds — the more PRs in flight, the more frequently authors get ejected and have to rebase, creating a frustrating cycle of churn.
We want to solve this by using git history to automatically determine migration ordering — when concurrent migrations create multiple heads, order them by when they were first introduced in git, so that the merge queue can resolve the ordering deterministically without human intervention. This requires being able to swap in a custom RevisionMap subclass that overrides _topological_sort().
Today there is no way to customize the ordering behavior without monkey-patching internals. The RevisionMap class is instantiated directly inside ScriptDirectory.__init__() with no way to substitute a subclass.
Proposed Solution
Add a revision_map_class configuration option to ScriptDirectory that accepts a dotted Python path to a RevisionMap subclass. This would allow external packages (e.g. a hypothetical alembic-git-ordering) to provide custom ordering logic by overriding _topological_sort() or other methods, without any changes to Alembic core.
This is a minimal, non-breaking change: a single new keyword argument with a None default, and a config option that is entirely opt-in.
Use Cases
- Merge queue compatibility: In CI merge queues (GitHub, Mergify, etc.), concurrent migrations cause repeated head conflicts that eject PRs. Authors must rebase and update
down_revision each time, which compounds with team size. A git-history-aware RevisionMap could order unrelated migrations deterministically, eliminating this manual churn.
- Git-history-based ordering: Order concurrent migrations by their first commit date, giving a stable timeline-based ordering across branches.
- Custom merge strategies: Organizations with many parallel branches could implement project-specific rules for how unrelated migrations should be sequenced.
Current Workarounds
The only current options are:
- Monkey-patching
RevisionMap or ScriptDirectory in env.py — fragile and breaks across Alembic upgrades
- Forking Alembic — heavy-handed for a small customization point
- Manually rebasing and updating
down_revision every time a PR gets ejected — the status quo we're trying to escape
We have a PR ready at #1805 that implements this.
Problem
We run a high-velocity monorepo where multiple teams land migrations concurrently. In our merge queue, when two PRs each add a migration, the second one to merge discovers there are now two Alembic heads. This kicks the PR out of the merge queue and requires the author to manually rebase and update their migration's
down_revisionto point at the new head, re-push, and re-enter the queue. With many developers contributing migrations, this compounds — the more PRs in flight, the more frequently authors get ejected and have to rebase, creating a frustrating cycle of churn.We want to solve this by using git history to automatically determine migration ordering — when concurrent migrations create multiple heads, order them by when they were first introduced in git, so that the merge queue can resolve the ordering deterministically without human intervention. This requires being able to swap in a custom
RevisionMapsubclass that overrides_topological_sort().Today there is no way to customize the ordering behavior without monkey-patching internals. The
RevisionMapclass is instantiated directly insideScriptDirectory.__init__()with no way to substitute a subclass.Proposed Solution
Add a
revision_map_classconfiguration option toScriptDirectorythat accepts a dotted Python path to aRevisionMapsubclass. This would allow external packages (e.g. a hypotheticalalembic-git-ordering) to provide custom ordering logic by overriding_topological_sort()or other methods, without any changes to Alembic core.This is a minimal, non-breaking change: a single new keyword argument with a
Nonedefault, and a config option that is entirely opt-in.Use Cases
down_revisioneach time, which compounds with team size. A git-history-awareRevisionMapcould order unrelated migrations deterministically, eliminating this manual churn.Current Workarounds
The only current options are:
RevisionMaporScriptDirectoryinenv.py— fragile and breaks across Alembic upgradesdown_revisionevery time a PR gets ejected — the status quo we're trying to escapeWe have a PR ready at #1805 that implements this.