Skip to content

Fix concurrent index migrations with schema-driven multitenancy #610#699

Open
RylandBangerter85 wants to merge 3 commits intoash-project:mainfrom
RylandBangerter85:fix-concurrent-index-multitenancy
Open

Fix concurrent index migrations with schema-driven multitenancy #610#699
RylandBangerter85 wants to merge 3 commits intoash-project:mainfrom
RylandBangerter85:fix-concurrent-index-multitenancy

Conversation

@RylandBangerter85
Copy link

Addressed @zachdaniel’s feedback: migration_requires_no_transaction? now relies only on the compiled module’s metadata via mod.__migration__(), and no longer reads the migration file.

Solution

Updated AshPostgres.MultiTenancy.migrate_tenant/3 to:

  1. Detect migrations that require no transaction (via @disable_ddl_transaction in the compiled module metadata)
  2. Run those migrations outside any transaction using Ecto.Adapters.SQL.checkout/3
  3. Keep backward compatibility for regular migrations

Changes

  • lib/multitenancy.ex: Added migration_requires_no_transaction?/1 and run_migration_without_transaction/4
  • test/concurrent_index_multitenancy_test.exs: Added regression tests for:
    • Concurrent index migrations with create_tenant!
    • Regular migrations (backward compatibility)
    • Mixed migrations (concurrent + non-concurrent)
    • Multiple concurrent indexes in one migration

Technical notes

  • Uses the compiled module’s __migration__/0 metadata for disable_ddl_transaction instead of scanning the file
  • Covers attributes set programmatically via Module.put_attribute/3

Contributor checklist

Leave anything that you believe does not apply unchecked.

  • I accept the AI Policy, or AI was not used in the creation of this PR.
  • Bug fixes include regression tests
  • Chores
  • Documentation changes
  • Features include unit/acceptance tests
  • Refactoring
  • Update dependencies

RylandBangerter85 and others added 3 commits February 4, 2026 13:47
- Detect migrations with @disable_ddl_transaction attribute
- Run concurrent index migrations outside transaction context
- Use Ecto.Adapters.SQL.checkout to get fresh connection
- Add comprehensive test suite for concurrent index scenarios
- Maintain backward compatibility with regular migrations

Fixes issue where CREATE INDEX CONCURRENTLY fails when creating tenants
…tion check

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@zachdaniel
Copy link
Contributor

I've actually just realized unfortunately a fundamental issue with this approach that I didn't consider the first time. Specifically, migrations often depend on each other, i.e one migration adds a table, another migration adds an index to that table. But in postgres, DDL migrations are transactional, meaning they won't be visible to migrations that are running outside of a transaction 😢

I think our only actual answer here is instead to check if we are running inside of a transaction while doing this and provide the user with guidance that they should disable the transaction on the action they are running. I don't think its possible to solve this in reality 😓

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