Skip to content

chore(migrations): delete 0001, and drop the duplicate indexes it created - #139

Merged
hsinatfootprintai merged 1 commit into
mainfrom
chore/drop-redundant-0001
Aug 14, 2026
Merged

chore(migrations): delete 0001, and drop the duplicate indexes it created#139
hsinatfootprintai merged 1 commit into
mainfrom
chore/drop-redundant-0001

Conversation

@hsinatfootprintai

Copy link
Copy Markdown
Contributor

What was wrong with 0001

0001_add_query_indexes re-declared indexes that GORM's AutoMigrate already creates from index: struct tags on the models:

ModelDocument.ModelProjectID     `gorm:"...;index:docScope,priority:1"`
ModelDocument.ModelCollectionID  `gorm:"...;index:docScope,priority:2"`
ModelDocument.CreatedAt          `gorm:"...;index:docScope,priority:3"`

Same columns, different names — AutoMigrate emits docScope, the migration emitted idx_restcol_documents_docscope, both over (model_project_id, model_collection_id, created_at). Same story for the two collection indexes.

Because CREATE INDEX IF NOT EXISTS matches on name and the names differ, its guard never fired. Applying it produced a second index over identical columns rather than doing nothing:

restcol-collections        :: idx_restcol-collections_model_project_id           (AutoMigrate)
restcol-collections        :: idx_restcol_collections_model_project_id           (0001)
restcol-collections-schema :: idx_restcol-collections-schema_model_collection_id (AutoMigrate)
restcol-collections-schema :: idx_restcol_collections_schema_model_collection_id (0001)
restcol-documents          :: docScope                                           (AutoMigrate)
restcol-documents          :: idx_restcol_documents_docscope                      (0001)

Six indexes where three suffice — write throughput and disk for no read benefit. Evidence: FootprintAI/grandturks#986.

So 0001 was not merely unapplied, which is what FootprintAI/grandturks#984 concluded from the manifests. It was better left unapplied.

Why delete rather than rename its indexes to match

A migration that re-declares what the models already declare is a second source of truth for one schema — and the models are the copy that services actually run. Renaming would keep both in sync by hand forever.

The README now says so, so nobody re-adds it:

Do not re-add index migrations for indexes struct tags can express. Add a migration when the change is one struct tags cannot describe — a backfill, a data purge, an index built concurrently, a column rewrite.

Why 0003 as well

Deleting 0001 stops the duplicates being created; it does not remove them where they exist. And they do exist: FootprintAI/grandturks#987 added a demo-box runner that applies every migrations/*.up.sql in order, so any box brought up on an existing volume since then has them.

0003 drops only the migration-created names. The AutoMigrate ones are the real indexes and stay — the two sets are distinguishable because GORM quotes the hyphenated table name (idx_restcol-collections_…) where 0001 used underscores (idx_restcol_collections_…).

Its down migration is a documented no-op, as with 0002: recreating duplicates would restore the problem, so a truthful revert does nothing.

Verified end to end on a real postgres

  1. seeded a fresh database with AutoMigrate → 3 indexes
  2. applied the now-deleted 0001 to reproduce the damaged state → 6 indexes
  3. applied 00033 indexes, and confirmed the survivors are AutoMigrate's over the expected columns
  4. re-ran 0003 → no-op

Numbering is not reused (0003 follows 0002), so no environment that recorded a version sees a different migration under an old number.

For consumers

grandturks copies these files into deploy/demo/restcol-migrations/ with a drift test, so it needs the copy of 0001 removed when it next bumps the pin. Flagging rather than leaving it to a red test.

Refs: FootprintAI/grandturks#986, FootprintAI/grandturks#984, FootprintAI/grandturks#987

…ated

0001_add_query_indexes re-declared indexes that GORM's AutoMigrate already
creates from index: struct tags on the models. Same columns, different names:
AutoMigrate emits "docScope", the migration emitted
"idx_restcol_documents_docscope", both over
(model_project_id, model_collection_id, created_at). Same for the two
collection indexes.

Because CREATE INDEX IF NOT EXISTS matches on name and the names differ, its
guard never fired: applying it produced a second index over identical columns
rather than doing nothing. Measured on a database built by AutoMigrate and then
migrated - six indexes where three suffice, costing write throughput and disk
for no read benefit. Evidence in FootprintAI/grandturks#986.

So 0001 was not merely unapplied, as grandturks#984 concluded from the
manifests - it was better left unapplied. Deleting it rather than renaming its
indexes to match: a migration that re-declares what the models already declare
is a second source of truth for one schema, and the models are the one that
services actually run.

0003 removes the duplicates on environments that did apply it. That is not
hypothetical: grandturks#987 added a demo-box runner that applies every
migrations/*.up.sql in order, so any box brought up on an existing volume since
then has them. Only the migration-created names are dropped; the AutoMigrate
ones are the real indexes and stay. The two sets are distinguishable because
GORM quotes the hyphenated table name where 0001 used underscores.

Verified end to end on a real postgres: seeded with AutoMigrate, applied the
old 0001 to reproduce the damaged state (6 indexes), applied 0003, confirmed
the 3 survivors are AutoMigrate's over the expected columns, and confirmed a
second run is a no-op.

Numbering is not reused - 0003 follows 0002 - so no environment that recorded a
version sees a different migration under an old number.

Note for consumers: grandturks copies these files into
deploy/demo/restcol-migrations/ with a drift test, so it needs the copy of 0001
removed when it next bumps.

Refs: FootprintAI/grandturks#986, FootprintAI/grandturks#984, FootprintAI/grandturks#987

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@hsinatfootprintai
hsinatfootprintai merged commit bbcb777 into main Aug 14, 2026
2 checks passed
@hsinatfootprintai
hsinatfootprintai deleted the chore/drop-redundant-0001 branch August 14, 2026 05:39
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.

1 participant