Changelog
0.6.1 (2026-10-25)
Bug fixes
- Finish creating or deleting an index when storage answers the registry write with a server error (99aaeae)
- Give up index claims before they lapse when the leadership table cannot be renewed (73cf782)
- Keep acknowledged documents when an index closes on an interrupted thread (8dc9509)
- Keep manifest and leadership fields from newer versions during a rolling upgrade (ad8c8d3)
- Keep pulls working when a push lands in storage but its local manifest write fails (8938a53)
- Retry the push of a handover flush that failed and was called off (a8faa4c)
- Stop a failed index create from removing an index another node created under the same name (1d16164)
- Stop a failed ownership notice from handing an index over without pushing it (ddfcecb)
- Stop another node taking an index while the shutdown flush is still pushing it (3c971ae)
- Stop losing writes that arrive while an evicted index pushes its last commit (ec2232b)
- Stop reporting a conflict after a push whose manifest write landed without an answer (9e29488)
- Stop two processes with the same node ID from writing the same index (d03c054)
0.6.0 (2026-10-04)
Features
- Allow fallback fields when sorting (2a8fcd8)
Bug fixes
- Answer 400 instead of 500 for a distance-sort cursor that holds no distance (e9138a9)
- Answer 400 instead of 500 for a key expiry later than a key can store (31afff2)
- Answer 400 instead of 500 when a string value is too long to index (7035e66)
- Answer 400 instead of 500 when a text or boolean field gets the wrong JSON type (a08deca)
- Answer 404 instead of restoring search settings deleted during a PUT with If-Match: * (b086567)
- Answer index:unsupported instead of a 400 when the live generation needs a newer engine (bc80dca)
- Close an index that was still opening when it was deleted (9a8d4e0)
- Continue paging when a cursor comes from a larger index instead of answering 500 (b436821)
- Count requests that match no route as UNKNOWN instead of by their path (209933a)
- Delete an index created on another node without a false 404 (fb5e3e0)
- Keep a recreated index’s objects when an old removal sweep runs at the same time (3499ef1)
- Keep acknowledged writes when an index is handed over after a failed push (1497bc9)
- Keep indexes readable when two nodes push after the manifest was removed (2fcd6ef)
- Keep keys and permissions from newer versions when an older node changes the keys (54b92fd)
- Keep pulling an index after a pull fails with an unexpected error (c6130a5)
- Keep ranking from using a signal that an update removed (8c8f7ff)
- Keep the index tie breaker when a fallback sort starts on the same field (25e681b)
- Keep the removal mark of an index deleted while another node creates it (8301b59)
- Keep writes a node takes during a quick lose-and-regain of an index (d27cca6)
- Refuse a cursor sent with another locale instead of skipping or repeating hits (8866fe9)
- Refuse a JSON body that holds more than one value (3f17008)
- Refuse a primary key of the wrong JSON type (36eab99)
- Refuse a request that gives the same JSON property twice instead of keeping the last value (84e8283)
- Refuse a zero knn vector on a cosine field instead of scoring every hit NaN (e5004c0)
- Refuse an unencoded ; in request paths (4d3f85b)
- Refuse definition changes that move a field name onto a wildcard field that indexes it differently (a315000)
- Refuse definition changes that would block every later write of an indexed field (9bb85a2)
- Refuse key index patterns that no index name can match (f033ee6)
- Refuse to promote or delete a generation of an index that needs a newer engine (5dc8b99)
- Report removed field locales as an incompatible definition change (0c02be8)
- Restore the remote definition and change log when a pull follows a refused push (c3c666f)
- Skip an NDJSON line that is valid JSON but not an object instead of failing the batch (895ab1e)
- Stop a concurrent partial update from bringing back documents a delete by query removed (a9f4cc7)
- Stop a freshness wait from timing out when the index is promoted mid-wait (13d90c2)
- Stop a key granted one generation from cancelling the reindex of another (e91a293)
- Stop a late key refresh from bringing a revoked key back (5bcf276)
- Stop a node that lost an index from keeping the documents it gave up (d7e8e8a)
- Stop a promoted reindex from keeping signals the source index removed (b1017c7)
- Stop answering with old search settings after a revert or a second removal (3375425)
- Stop deeply nested definitions from turning empty after the index reopens (c6582b6)
- Stop deleting newer indexes after you restore an older registry in local mode (f39a138)
- Stop keys granted only an index’s generations from changing its search settings (c238a88)
- Stop locale patches from leaving stale values in the default locale (ff0d713)
- Stop pushing a handed-over index when its claim is taken during the handover (de40f93)
- Stop readers from serving a deleted index after it is created again under the same name (4face53)
- Stop reads from answering from a demoted generation after a roll back (a15fdf5)
- Stop the refresh pass from removing an index created while it ran (0179b1d)
- Treat -0.0 as 0.0 in float and double fields so filters and facets agree at zero (702d783)
- Warn when EXOFIND_NODE_ADDRESS has no scheme or an invalid host name (30ecc6e)
0.5.0 (2026-09-15)
Features
- Allow large chunked streaming to batch endpoints (5384ed7)
- Index a single document by its key (a9ab104)
- Look up one document by its key over the API (0029295)
- Support for freshness tokens to be able to request up to date searches (17e3474)
- Unify and document change path selection for documents and index settings (85dfd8d)
0.4.1 (2026-09-13)
Bug fixes
- Ensure that a node does not break during start up while generating OpenAPI docs (3d5d827)
0.4.0 (2026-09-13)
Features
- Allow keys to be rotated and protect against accidental removals of last key (5a850df)
- Answer 304 when a GET carries an ETag and the resource is unchanged (3517e54)
- Answer every failed request with a standard JSON error body (96bb3f3)
- Filter and page the index, key and reindex listings (a9b9080)
- Generate real query and field types in OpenAPI clients (6104987)
- Improve batch indexing error handling and allow skipping docs with errors (f626075)
- Introduce shared cache settings for the entire node (983b10a)
- Let a deployment cap how many facet values and suggestions a request may ask for (012c483)
- Measure facet value and explain requests (dcedc22)
- Normalize error codes for numeric ranges (7d9f1e7)
- Publish a named Interpret union in the OpenAPI document (7f8acf7)
- Read and cancel a reindex job under /admin/reindexes (00ff93d)
- Reindex jobs are now identifiable and carry more metadata (e9bbf70)
- Rename every error code by family, request part and defect (fd4cb1a)
- Rename index:not-found to index:not_found (045382b)
- Rename some request:update errors to index:update (67774a4)
- Rename the live generation
liveGenerationwhen listing indexes (493d02f) - Report enums in the REST API as lowercase (2c1ac3c)
- Report every error path in the REST API using dotted form (4af6fd5)
- Report which index generation answered a search (51663ce)
- Require all parameter to delete all documents (21d1e36)
- Require indexes.promote permission when auto-promoting reindex (eeb47ec)
- Return missing primary keys as text (561faac)
- Return the index with its ETag from commit and pull (068f6cb)
- Stronger If-Match application in the REST API (3be9a94)
- Support for ranking signals with non-indexing updates (402b301)
Bug fixes
- Accept a document key written as another JSON type in a PATCH body (4a6e2f4)
- Answer index:not_found when trying to reindex a non-existent index (1980fbe)
- Avoid sending back empty tieBreakers for rankings (53c6755)
- Cancel a queued reindex without a 15 second wait (b062e1a)
- Count the clauses of interpret targets against the search clause caps (a68d202)
- Ignore paging, sort and rescore in explain instead of validating them (8c89ca4)
- Index documents forwarded over HTTP/2 instead of reporting zero indexed (6933dbc)
- Keep a closing index copy from overwriting files (64051b3)
- Keep a registry repair from undoing a delete that lands while it runs (993f066)
- Keep a rescored search from paging into an empty page (33328ae)
- Keep a slow registry read from hiding an index another thread just created (1036215)
- Keep attempting to push indexes if a push fails (830c102)
- Keep registry entries a newer node wrote when an older node changes it (87ff74e)
- Keep the definition and change log intact when a node stops mid-write (7ce5358)
- Mark storage as removed when a delete cannot clear a local copy (6cf9dbf)
- Refuse a boost weight of NaN or Infinity instead of scoring with it (3204515)
- Report NDJSON document errors without a
documentsprefix (f314c49) - REST API now answers more calls with 4xx instead of 500 (2f9aad7)
- Return 400 for an invalid after parameter when reading documents (b4edb2e)
- Stop a refused reindex from leaving an empty generation behind (b2f2008)
- Stop omitting score from a search ranked by signals or a second pass (9812afd)
- Tell apart an empty
matchedand a blank field name, and point highlight errors at the field (9a44f8b)
Performance
- Cache typo and prefix matches on small segments too (ffba8f2)
- Reuse prefix automata across fields and requests (fe3257e)
- Speed up long and typo tolerant searches by reusing term lookups (1facf2d)
0.3.0 (2026-09-10)
Features
- Keep replaced index files in the bucket for a grace period before deleting them (7e361b4)
- Sweep orphaned objects from an open index on a timer (c29cce1)
- User queries can now match any of the words instead of all words (d4e5806)
Bug fixes
- A failover no longer loses recently written documents (c003f23)
- A lost index registry no longer deletes the indexes on a node (ae3d9b6)
- A push conflict no longer loses the documents written around it (4569113)
- Handle stale generations in Google Cloud Storage without getting stuck (7069e87)
- Keep writes made during a reindex instead of dropping them at the promote (b2c43b6)
- Pulled files that do not match the manifest are rejected instead of used (a602fe8)
- Recreating a deleted index no longer brings the old documents back (3f6a698)
- Stop a definition update from emptying an index when taking over indexing for it (37f04a8)
- Stop a failed push from handing an index over without its writes (efda453)
- Stop a rejoining node from deleting an index from storage (6eef1f7)
- Vanished manifests no longer makes readers drop their index files (f3ecdf6)
Documentation
- Add cross-links and related sections for new pages (50eec3a)
- Add search powered by project to website (b2aaab3)
- Add storage layout, glossary, write guarantees, testing and ranking pages (6018451)
- Improve example copy and relevance (38002ea)
- Limit snippets in the website search (233e2ac)
- Loading states for examples (a0a1593)
- Reset scroll when typing into the website search (3a1fd6e)
- Stop the loading bar sticking after pressing Back from a demo (66230b8)
0.2.0 (2026-09-06)
Features
- Improve Google Cloud Storage support (6b2a4d8)
- Support for AWS and file credentials for object storage (8adbea1)
Bug fixes
- Report work a shutdown interrupts as stopped instead of a warning (3f8a8b4)
Documentation
- Add in missing space before email (56294d0)
- Add info about who’s behind the project on the website (9861540)
0.1.0 (2026-09-06)
Features
- Ability to add query-time synonyms per index (c395813)
- Ability to limit the complexity of searches (8da8afb)
- Ability to list indexed documents (937345b)
- Ability to rebuild a lost or corrupt index registry (b32053a)
- Ability to request which nested objects matched a query (69d96ae)
- Ability to return each matched nested object as a hit of its own (b4aebfc)
- Ability to set a role on a field to simplify setup (ec2baae)
- Accept dynamic attribute names inside and for object fields (2fed904)
- Add benchmark utility (31d195d)
- Add Gujarati, Kannada, Malayalam, Marathi, Odia and Punjabi as supported locales (729e034)
- Add health check endpoints (b1cdd3b)
- Add locale support for Central Kurdish, Nepali and Chinese (Traditional) (d66dab0)
- Add Malay, Croatian and Bosnian as supported locales (da58cf6)
- Add Slovak and Slovenian as supported locales (bdde702)
- Add Urdu as a supported locale (4e8971b)
- Add Vietnamese as a supported locale (18f68c6)
- Allow disabling typo-tolerance for certain words (eda49ea)
- Allow nested objects to specify their key (562e53f)
- Allow objects to store, highlight and nest further down (6cd000e)
- Allow ranking signals on requests to compose with the index (d7f1764)
- Answer exact totals of value hits from index statistics (461b7e3)
- Answer locale specific fields in the locale the search asked for (3a6e488)
- Answer repeated facets from a cache and improve count refresh (be71979)
- Balance indexes between nodes based on write load (8f6c855)
- Cache the documents of search results in memory, (f75460d)
- Change nested documents without having to send them all (d7423cc)
- Change one document with PATCH (cb25ba3)
- Change only some settings with PATCH (6297850)
- Check for malformed sha256 root key at startup (2c6d2bb)
- Combine text and vector rankings by rank with a fuse clause (ce32a59)
- Count all facets in one sweep instead of one-by-one (34c41e9)
- Count object-field facets without collecting the matched values (042fe0e)
- Count value hits straight off their own conditions (b6bffaa)
- Count wide facet scopes a value at a time (0f82564)
- Custom document serializing to reduce memory needed to write them (76327e9)
- Cut allocations when counting facets over object fields (264f850)
- Declare an index’s locales once instead of on every field (b85b028)
- Endpoint to explain how a hit scored (7812481)
- Export metrics surrounding node and index health (e469cd6)
- Fill a new generation by reindexing from the one it replaces (52febbd)
- Filter inside nested objects without emptying their own facets (2d698b7)
- Forward index writes to the correct indexer (ccc7ea1)
- Hierarchy facets allocate less by reusing parsed paths per segment (22ae8ef)
- Highlight a page of hits with one term lookup per segment (cb64d23)
- Improve facet performance with batched counting and bitset collection (cb2be5f)
- Improve hierarchy facet speed via caching (2c67e39)
- Improve index and setting refresh timings (efad724)
- Improve JVM defaults when running in Docker (81e8af0)
- Improve logging of startup, indexing etc (940bae2)
- Improve query speed based on benchmark numbers (8208cb1)
- Improve query speed when using ranking signals (8009dd7)
- Improve sort and facet performance for number fields (1781412)
- Improve speed of cold typo searches (7ec0d9c)
- Improve speed of searches that ask for highlights (da7478a)
- Improve speed of sorting on distance (b918882)
- Include decimals in tookMs (c03614d)
- Indexer nodes now spread writes to indexes between them (d9bcf7a)
- Initial commit (3b3071f)
- Introduce nested vs flattened object representations (20090ae)
- Korean support for compound nouns (1cf9916)
- Let each document control if nested objects are surfaced in its place (fafce10)
- Let ranking be tuned per index without updating it (136ed4f)
- Metrics for how long indexes take to open (98e4fe0)
- OpenAPI documentation (4e3b12f)
- Order facet values as declared and label them per locale (84eae2c)
- Parse field values from query (59b82cb)
- Parse numbers in query strings into queries (d9786a4)
- Poll S3 less by utilizing the registry to carry update hints (fac537b)
- Prefix every environment variable with EXOFIND_ (694816a)
- Preload and warm facets when an index opens (8dacf08)
- Prepare an index for writing as soon as a node takes it over (5047ba7)
- Push an index in its merged form after writing stops (4f6695d)
- Read flat per-segment columns instead of doc values for facets (2d4b1c1)
- Record which documents change so a rebuild copy can be caught up (633b0b0)
- Record which reindex jobs are active to reduce S3 use (650a78b)
- Refuse searches asking for fields the index can never return (2c4f6c2)
- Reject dots in field names in favor of explicit objects (82df057)
- Remove deleted indexes from object storage after a grace period (5e2988d)
- Reopen the indexes a node served before it restarted (650b8a6)
- Rerank the best results in a second pass (6dc56b0)
- Return single fields from inside objects in search results (adff0b9)
- Rework locale data and support for Icelandic (a5d753e)
- Score text searches through dense norms instead of a sparse lookup (8d1949d)
- Search a document’s chunks by vector with knn inside a nested object (6da5f80)
- Search using multiple threads (1462daf)
- Searches no longer wait on a shared lock on the index (32aada5)
- Searches with typo tolerance ignore number typos (8e41a08)
- Speed up and reduce memory used when decoding source fields (eabe5d7)
- Speed up facets when only their own filter, or nothing, narrows the search (a13ed61)
- Speed up multi-word text search on fields that support autocomplete (51bf060)
- Speed up searches by disabling disjunction query tie-breaking (2bb0ed8)
- Speed up searches that repeat a misspelled or half-typed word (ee432c6)
- Speed up typo tolerant queries (77ef291)
- Speed up typo-tolerant search by walking each misreading less times (4e63300)
- Split Finnish compound words (d44290f)
- Spread the first orphan sweep of each index after a node restart (f17b8d7)
- Stop recounting facets when promoting sub-documents to hits (e516aff)
- Stop recounting whole-index object-field facets on every search (9d49155)
- Support for searching facet values by prefix (d9e3f7f)
- Support suggesting queries (cd25a1c)
- Switch highlights to use postings (683f744)
- The admin API now shows which node writes each index (9c89c69)
- When editing an index definition check compatibility before allowing (0405cca)
Bug fixes
- Adjust config names so that ENV-vars can reach them (49a2489)
- Create an index without it sometimes failing as readonly (46f4d3d)
- Documents accepted just before a shutdown survive a fast takeover by another node (4c40e98)
- Enable fsync of manifest and index files (d8df834)
- examples: Make sure the livsmedel example no longer renders [object Object] (3c23882)
- Keep index data when a node stops while a reindex copies (7dc85a4)
- Keep one slow index from delaying the failover of others (b05ed8d)
- Keep writing indexes when S3 reports a conditional write conflict (ad4c925)
- Reject malformed Authorization headers (f5cbea4)
- Stop a node whose claim lapsed from overwriting its successor’s work (207ed73)
- Stop a reindex from promoting after the index moves to another node (f9d8406)
- Stop reporting a failure for a registry change that was made (4fe8dbb)
- Upload every file again when the remote index was emptied (d19d2e4)
Documentation
- Add aside about locale data in the configuration section (352282e)
- Add cross-links to how-to guides (9220d7d)
- Add Discogs example to show off sub-documents (0611242)
- Add examples to REST API (5b11189)
- Add llms.txt and Markdown versions of website (45705dd)
- Add more documentation (8bcf0f6)
- Add number and field parsing to Discogs demo (4d92244)
- Add OpenGraph images (a0aabf1)
- Add some tentative deploy docs for Kubernetes (d271ed6)
- Clear filters when sample queries are pressed (b3637fa)
- Document how merged files are handled in the object storage bucket (b1cef52)
- Document some traps surrounding benchmarks (95ab7e8)
- Document that /q/metrics does not use authorization (2bf74f3)
- Document that EXOFIND_NODE_ADDRESS should be private or use https (f9302de)
- Fix example intros (691d2ec)
- Fold facets on smaller screen sizes (5a41150)
- Give proto files a documentation pass (52f7c13)
- How to for modelling dynamic attributes (e0e7cff)
- Improve frontpage copy and add links (b203359)
- Improve page transitions on website (a1e1844)
- Improve synonym docs (c5c2ec5)
- License under Apache 2.0 (949e22f)
- Move documentation site to exofind.dev (c06873a)
- Normalize names of pages (d4f3590)
- REST API section for website (8594b63)
- Reveal sidebar entries as website is navigated (7f235c6)
- Rework docs in an attempt to make them clearer (7b4ed67)
- Rework website theme (e1b406b)
- Rewrite the OpenAPI descriptions (2fe3bfd)
- Stop the page blanking when moving between documentation pages (f4cf27a)
- Update CLAUDE.md (d563de7)
- Update deployment shapes explanation with some more details (a3573fe)
- Update documentation skill (2e4f8b8)
- Update documentation skill (06f287b)
- Update documentation skill slightly (6edb000)
- Update explanation doc for index generations (4e460d0)
- Update website and tutorials (ec99cf8)
- Update website navigation (91c2d2c)
- Upgrade Astro and Starlight (c79dbde)
- Use bossa nova instead of gatefold as example query in Discogs demo (cfd5d8e)
- Website built from documentation and examples (93cb06f)
Internal
- Add CI and publish images to GHCR (054341b)
Exofind is built by Level Four AB and is available under the Apache License 2.0.