Flyway is authoritative for database indexes
Every database index in any Arda back-end service is declared and managed by a Flyway migration. Exposed-level .index(...) declarations on table objects are decorative — they do not create indexes at runtime and must not be added.
The rule
Section titled “The rule”| Where indexes live | Authoritative? |
|---|---|
Flyway migration scripts (src/main/resources/.../database/migrations/V*.sql) | Yes — single source of truth |
Exposed Table declarations using .index(...) | No — decorative; the schema-emit path is not invoked in any Arda deployment |
When adding, modifying, or removing an index:
- Author a new Flyway migration with the appropriate
CREATE INDEX,DROP INDEX, orALTER INDEXstatement. - Do not add a chained
.index(...)call on the ExposedTabledeclaration. Existing decorative declarations are scheduled for removal. - If the index requires
CREATE INDEX CONCURRENTLY(low-write-impact online deploys), use theexecuteInTransaction=falseFlyway sidecar and ensurecommon-module’sDbMigrationis configured withmixed=true+ the non-transactional advisory-lock mode (both already true post-PDEV-490).
Exposed offers a .index("idx_name") method on column declarations that appears to create the index but is part of Exposed’s schema-emit / DDL generation path. That path is invoked only by Exposed’s SchemaUtils.createMissingTablesAndColumns(...) and equivalents — which are not called in any Arda deployment pipeline. Arda relies exclusively on Flyway to apply DDL.
A .index(...) declaration on an Exposed Table therefore:
- Does not create the index at deploy time.
- Does not ensure the index exists in any environment.
- Misleads readers into believing an index is in place when only Flyway can guarantee it.
Two such decorative declarations existed in common-module prior to PDEV-490: AbstractScopedUniverse’s tenantId.index("TENANT_ID_INDEX") and similar patterns. Both have been removed; the Flyway tree carries the real tenant_id index for every consumer that uses one.
Auditing index coverage
Section titled “Auditing index coverage”To verify that an Exposed ScopedTable consumer actually has the indexes it expects:
grep -rE "CREATE INDEX|create index" <service>/src/main/resources/**/database/migrations/Or query the live database:
SELECT tablename, indexname, indexdefFROM pg_indexesWHERE schemaname = 'public' AND tablename = '<table-name>'ORDER BY indexname;The PDEV-490 audit found that kanban_card was missing its tenant_id index despite an Exposed-level declaration — the index was added by Flyway as part of that project.
See also
Section titled “See also”- Bitemporal composite indexes — the index shapes used for latest-version-per-entity-id queries.
- AWS Advanced JDBC Wrapper integration — Flyway runs through
common-module’sDbMigration, which configuresmixed=trueand the session-level PostgreSQL advisory lock to permitCREATE INDEX CONCURRENTLYmigrations.
Copyright: (c) Arda Systems 2025-2026, All rights reserved
Copyright: © Arda Systems 2025-2026, All rights reserved