File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -1636,8 +1636,22 @@ export async function migrateStep(
16361636 schema : string ,
16371637) : Promise < MigrateStepResult > {
16381638 try {
1639- // Begin transaction and acquire transaction-level advisory lock
1640- await client . query ( 'BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE' ) ;
1639+ // Begin transaction and acquire transaction-level advisory lock.
1640+ //
1641+ // IMPORTANT:
1642+ // We intentionally do NOT use SERIALIZABLE here.
1643+ //
1644+ // When multiple Replane instances start concurrently, they will all try to migrate.
1645+ // The first statement after BEGIN is `pg_advisory_xact_lock(...)`, which can block
1646+ // while another instance is migrating. In SERIALIZABLE mode, Postgres takes a
1647+ // consistent snapshot for the transaction at the beginning of the first statement,
1648+ // and keeping that snapshot while waiting can lead to spurious 40001 serialization
1649+ // failures once the lock is acquired.
1650+ //
1651+ // The advisory lock already provides mutual exclusion for migrations, so the extra
1652+ // SERIALIZABLE isolation is unnecessary and can actively hurt reliability in
1653+ // multi-instance deployments.
1654+ await client . query ( 'BEGIN' ) ;
16411655 await client . query ( /*sql*/ `SELECT pg_advisory_xact_lock(hashtext('migrations_${ schema } '));` ) ;
16421656
16431657 // Ensure migrations table exists
You can’t perform that action at this time.
0 commit comments