Result cache
How repeated searches are served from cache, how the cache is invalidated on every write, what bypasses it, and how to tune cacheTtl.
Repeated identical searches are answered from a cache instead of the engine. You do not have to do anything to use it; this page explains the rules so the results are never surprising.
Two layers
| Layer | Where | Key |
|---|---|---|
| Result cache | Redis, above the search service | organization + index + revision + hash of the normalized request |
| Engine cache | the search service (use_cache, cache_ttl) | the engine's own request hash |
Both use the index's cacheTtl.
Freshness: revisions, not TTL guessing
Every index has a revision counter. Every write increments it: documents, settings, schema, profiles, rules, synonyms, curations, presets, stemming and alias swaps (reindex, restore). A bumped revision makes every older cache entry unreachable at once, so a search right after an upsert always reaches the engine.
What is never cached
- Requests with ACL principals (per-user visibility).
- Requests with a visitor
session_id(personalization). explain=true.- Indexes with
cacheTtlset to0. - Responses whose reranker was skipped.
Bypassed requests neither read nor write the cache.
Billing
A cached answer is still a billed search: quota is reserved and committed and the query is logged exactly as for an engine answer. The cache makes search faster, not cheaper.
Tuning cacheTtl
Index → Search settings → Cache TTL, stored as settings.search.cacheTtl
(seconds).
| Value | Effect |
|---|---|
60 | Default |
0 | Cache off for this index |
up to 86400 | Maximum (one day) |
Because invalidation is driven by revisions, a long TTL does not serve stale results after a write; it only keeps entries for unchanged data longer.
Observing it
Hit rate per organization is shown in the console analytics. Operators see
aacsearch_cache_events_total in Prometheus format on /metrics.