Skip to content

ADR 0005: External search backends with unified search configuration

Status

Accepted

Context

GeneralManager needs search that is: - Typo tolerant and relevant for user-facing queries. - Independent of any single database backend. - Compatible with non-database interfaces. - Able to search across multiple managers and multiple indexes. - Exposed via GraphQL with mixed-type results.

Decision

Introduce a backend-agnostic search integration based on: - Manager-level search configuration (IndexConfig + FieldConfig). - External search backends (Meilisearch first, then Typesense and OpenSearch/Elasticsearch). - Optional in-project DevSearch backend for local development. - A single global GraphQL search query with an index parameter. - Indexing and update hooks decoupled from database operations.

Key rules: - Use a type-scoped document ID format for all managers: {TypeLabel}:{identification-json} (e.g., Project:{"id":1}) so IDs are stable and unique across manager types. All indexing and lookup logic that uses manager.identification, document keys, or ID construction must follow this combined format. - Index only configured fields (or to_document when provided). - No runtime overrides for per-index filters or boosts. - Respect manager permissions via get_read_permission_filter() in the GraphQL resolver.

Alternatives considered

1) Database-native search only (FTS / trigram) - Rejected: does not cover non-DB interfaces and ties search to the DB backend. 2) One GraphQL query per index - Rejected: schema churn as indexes evolve; higher maintenance. 3) Runtime overrides of boosts and filters - Rejected: harder to reason about relevance, caching, and permissions.

Consequences

  • Requires an indexing pipeline and an external service in production.
  • Enables consistent multi-manager search across databases and interfaces.
  • Keeps the public GraphQL schema stable as indexes evolve.
  • Forces relevance tuning to live in code/config (predictable behavior).

Follow-up work

  • Implement backend protocol and Meilisearch adapter.
  • Add Typesense and OpenSearch/Elasticsearch adapters.
  • Implement GraphQL search(index=...) resolver and union type.
  • Add permission-aware search tests.
  • Document setup steps for each backend.