Skip to content

πŸ› startMongoose resolves before index builds β€” unique-index idempotency can double-apply on a fresh databaseΒ #3990

Description

@PierreBrisorgueil

What β€” mongoose.connect() resolving does not mean indexes exist: autoIndex builds run in the background and startMongoose() never awaits them. Any logic that relies on a unique index for idempotency (e.g. BillingUsage's {organizationId, weekKey} replay protection turning a duplicate upsert into a caught E11000) has a window on a brand-new database where the first writes land before the index exists β€” the "replay" then creates a second, distinct document instead of no-oping.

Why β€” On a fresh deploy (or any fresh database, e.g. an integration-test worker DB) metered usage can double-count during the index-build window. Surfaced as an intermittent replay-idempotency test failure in a downstream consumer (~1-in-5 on fresh DBs); confirmed by trace (replay write matched a different docId) and by the fix (awaiting index builds β†’ 0 failures in 35 runs).

Scope β€”

  1. lib/services/mongoose.js / lib/app.js boot: after connect + model registration, await index readiness for every model (Promise.all(modelNames.map((n) => model(n).init()))) before the app reports ready.
  2. Adjacent bug this surfaces: modules/billing/models/billing.usage.model.mongoose.js legacy {organizationId, month} unique index declares partialFilterExpression: { weekKey: { $exists: false } } β€” $exists: false is not supported in partial filters, so this index has silently never been created. Decide: fix the filter to a supported form or retire the legacy index if the month path is dead.
  3. Tests: boot-time assertion that indexes are ready; replay-idempotency test on a fresh DB stays deterministic.

Created via /dev:issue

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions