Sync issues bigint indexes batch one for self-managed
What does this MR do and why?
Creates the first batch of bigint-equivalent indexes on the issues table synchronously, for the integer-to-bigint ID conversion tracked in #629827 (closed).
The asynchronous preparation (!251347 (merged)) only creates these indexes on GitLab.com, where prepare_async_index schedules them for weekend creation. Self-managed instances need them created synchronously. This MR is the follow-up synchronous step for that batch.
The six async indexes have been verified to exist in production, so this migration is a no-op on GitLab.com — add_concurrent_index detects each existing index by name and skips it.
Columns / indexes in this batch
The six free single-column FK columns that are not coupled to id:
| Index (bigint equivalent) | Column | Migration |
|---|---|---|
index_issues_on_closed_by_id |
closed_by_id |
20260903090001 |
index_issues_on_duplicated_to_id |
duplicated_to_id |
20260903090002 |
index_issues_on_last_edited_by_id |
last_edited_by_id |
20260903090003 |
index_issues_on_moved_to_id |
moved_to_id |
20260903090004 |
index_issues_on_promoted_to_epic_id |
promoted_to_epic_id |
20260903090005 |
index_issues_on_updated_by_id |
updated_by_id |
20260903090006 |
The bigint index names are generated with bigint_index_name from Gitlab::Database::MigrationHelpers::ConvertToBigint, matching the names created by the async preparation.
Why one index per migration
issues is a large table. Each index is created in its own post-deployment migration so every migration stays within the concurrent-operation time budget for post-deployment migrations. These are not running in .com, but still, there are some large self-hosted instances. Also, in case of errors, it will be easier to retry/fix a single index at the time.
Guarding
Each migration only runs where its *_convert_to_bigint column exists. On instances where all IDs are already bigint (for example newer installs), the conversion column is absent and the migration skips.
Migration output
db/structure.sql is intentionally unchanged: it already reflects the final all-bigint state used by new instances, and the temporary bigint_idx_* indexes live on *_convert_to_bigint columns that are not part of that schema.