Skip to content

fix: use CONCURRENTLY only for non-empty schemas to prevent deadlock#493

Closed
cdbartholomew wants to merge 1 commit intomainfrom
fix/remove-concurrently-from-migrations
Closed

fix: use CONCURRENTLY only for non-empty schemas to prevent deadlock#493
cdbartholomew wants to merge 1 commit intomainfrom
fix/remove-concurrently-from-migrations

Conversation

@cdbartholomew
Copy link
Contributor

Summary

  • Fixes a deadlock where CREATE INDEX CONCURRENTLY in migration files hangs the server when provisioning new tenant schemas while the worker is running
  • CONCURRENTLY waits for ALL open transactions database-wide. The worker's polling loop always has a transaction open, so CONCURRENTLY waits forever
  • This happens in both dev (worker in-process) and production (worker in separate pod) — same database, same problem

Fix

Migrations now check whether the target table has data before choosing the index creation strategy:

  • Empty tables (new tenant provisioning): regular CREATE INDEX — instant, no deadlock risk
  • Tables with data (existing schemas during rolling deployments): CREATE INDEX CONCURRENTLY — avoids blocking writes on large tables

Test plan

  • Full integration test suite passes (87/87, no deadlocks, 28s)
  • Verified against the previously deadlocking scenario (new tenant creation while worker is active)
  • Pre-existing test failures unchanged (api key format, auto-recharge, mailpit)

CREATE INDEX CONCURRENTLY waits for ALL open transactions database-wide
before the index becomes valid. When a new tenant schema is provisioned
at runtime, the worker task poller holds an idle-in-transaction
connection from its polling loop. CONCURRENTLY sees this and waits
forever — deadlocking the server.

This happens whether the worker runs in-process (dev/tests) or in a
separate pod (production), since they share the same database.

Fix: check if the target table has data before choosing the index
creation strategy. Empty tables (new tenant provisioning) use regular
CREATE INDEX which is instant and has no deadlock risk. Tables with
data (existing schemas during rolling deployments) continue to use
CONCURRENTLY to avoid blocking writes on large tables.
@nicoloboschi
Copy link
Collaborator

the real problem is that the worker keeps the transaction open for the entire consolidation - I'm gonna fix that and close this one - we need to be able to create indices with CONCURRENTLY or they will be super slow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants