Skip to content

Latest commit

 

History

History
62 lines (47 loc) · 2.55 KB

File metadata and controls

62 lines (47 loc) · 2.55 KB

ADR 0009: Search index method version for reconciliation

Status

Accepted (2026-05-31)

Context

ADR 0007 introduced search_entity_indexing_map and a daily backfill cron that re-indexes entities when a map row is missing or when the domain entity’s last_modified_time is newer than the map row’s last_modified_time.

That catches entities that changed after they were indexed, but not entities whose indexing algorithm changed while the domain row stayed the same. Examples: different fields sent to Algolia, a new object-id scheme, or loading extra related data (notes, tags, contacts) into the search document. After such a change, the map can look “fresh” even though search results are wrong.

Re-indexing everything on deploy would work but is expensive and unnecessary when only the indexer changed.

Decision

  1. Constant INDEX_METHOD_VERSION
    Defined in SearchEntityIndexService (entity_index.py). It is the version of the indexing method, not of the entity. Bump it when indexing logic changes in a way that requires re-processing unchanged domain rows.

  2. Column on the map row
    SearchEntityIndexingRecord.index_method_version is persisted in search_entity_indexing_map. Every successful index() writes the current constant. Existing rows are backfilled via migration to the version in use at migration time.

  3. Backfill trigger
    SearchIndexBackfillDoAllUseCase re-indexes when any of the following holds:

    • no map row for the entity;
    • domain last_modified_time is newer than the map row;
    • row.index_method_version < INDEX_METHOD_VERSION.
  4. Rollout
    To force a full re-index after an indexer change: increment INDEX_METHOD_VERSION, deploy, and let the existing daily backfill (plus normal post-mutation indexing for changed entities) converge. No separate one-off job or manual SQL is required.

Consequences

  • Cheap steady state: Unchanged entities with a current version are not re-indexed on every cron run.
  • Targeted invalidation: Only rows stamped with an older method version are picked up after a bump, in addition to the usual stale/missing checks.
  • Operational contract: Changing how entities are indexed without bumping the version leaves stale search data until something else triggers a re-index. Bumping the version is the explicit signal that reconciliation should run.
  • Schema: Requires migration when the column is first added; later bumps are code-only.

Related

  • ADR 0007 — search entity indexing map and hourly backfill