Skip to content
Latchkey

Ecto Migration Lock Timeout in CI

Ecto acquires a database advisory lock so two migrators cannot run at once. If a previous migrator died holding it, or another run is migrating concurrently, ecto.migrate waits - and can time out. The stale-lock case is transient.

What this error means

mix ecto.migrate stalls while acquiring the migration lock and then fails with a connection/lock timeout. It commonly follows a cancelled or OOM-killed CI job that held the advisory lock when it died.

Elixir output
** (DBConnection.ConnectionError) tcp recv: closed / timed out while
waiting for the Ecto migration advisory lock to be released

Common causes

Stale advisory lock from a killed run

A prior migrator was cancelled or OOM-killed before releasing the advisory lock. The next run waits on it. Advisory locks are session-scoped, so a truly dead session’s lock clears once that connection is gone.

Concurrent migrations

Two pipelines migrating the same database at once contend for the lock; one waits while the other runs.

How to fix it

Retry once the stale session clears

A bounded retry usually succeeds once the dead migrator’s connection is reaped and its advisory lock releases.

Terminal
for i in 1 2 3; do
  mix ecto.migrate && break
  echo "migration lock retry $i"; sleep 5
done

Serialize migrations to avoid real contention

  1. Use a CI concurrency group so only one migration job runs against a database at a time.
  2. Avoid two pipelines targeting the same database concurrently.
  3. Set a step timeout so a stuck lock surfaces fast instead of hanging.

Disable the lock only when safe

For a single-writer ephemeral CI database you can opt out of the migration lock, but never on a shared database.

config/test.exs
# config/test.exs
config :my_app, MyApp.Repo, migration_lock: false

How to prevent it

  • Serialize migration jobs with a CI concurrency group.
  • Set step timeouts so a stuck lock fails fast.
  • Keep one migrator per database; rely on the advisory lock for safety.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →