Kuzzle 2.61 #
Released: 2.61.0 on 2026-11-04, after nine betas (2.61.0-beta.1 on 2026-10-30 to 2.61.0-beta.9).
The GitHub release notes list every commit. This page tells you what changes for you. For what to check before you upgrade, read Upgrading from 2.60.
In short #
2.61 opens Kuzzle to other storage engines. A storage engine can now come as a separate npm package, a storage driver, that you install next to Kuzzle and name in the configuration. Elasticsearch 7 and 8 keep working exactly as before: they are now Kuzzle's built-in drivers, shipped as packages Kuzzle installs with itself.
What you need to do #
Nothing. An Elasticsearch 7 or 8 setup needs no change, in its configuration or its dependencies.
Before you move to another storage engine, check your plugins and your application: with a driver set, majorVersion no longer tells which client app.storage.storageClient or context.constructors.ESClient gives. Ask Kuzzle with app.storage.getEngine() or context.accessors.getStorageEngine() instead (see Upgrading from 2.60).
If your code or your clients match the text of storage error messages, check it: they no longer say "Elasticsearch" (see Upgrading from 2.60).
What's new #
- Storage drivers. Set
services.storageEngine.driverto the name of a driver package to run Kuzzle on another storage engine. Kuzzle checks the driver at startup and refuses to start if it is missing, invalid or not made for this Kuzzle version. The API does not change: queries and mappings are still written in the Elasticsearch format. Read Storage Drivers. - Capabilities. A driver may not support every feature (aggregations, mapping changes, statistics, update by query). A request needing one it does not support is rejected with a clear
services.storage_driver.unsupported_capabilityerror. The built-in drivers support them all. - Same driver on every cluster node. A node running another driver, or another version of it, than the rest of the cluster is refused when it joins, with a
cluster.join.storage_driver_mismatcherror. Nodes running the built-in Elasticsearch drivers are compared by Elasticsearch major version only: amajorVersion: "8"node is refused by"7"nodes, and a rolling upgrade from 2.60 with an unchanged configuration still works. A refused node is refused before it connects to the storage, so it writes nothing there (#3139). - Elasticsearch 7 and 8 as packages (2.61.0-beta.2). The built-in drivers now live in their own packages,
kuzzle-storage-es-7andkuzzle-storage-es-8, which Kuzzle depends on and installs with itself: same code, same behavior, still selected bymajorVersion. Yourpackage.jsondoes not change. - Elasticsearch 9. Install the driver
kuzzle-storage-es-9next to Kuzzle and setservices.storageEngine.driverto"kuzzle-storage-es-9". It is Kuzzle's Elasticsearch 8 driver on the Elasticsearch 9 client: same mappings, same queries, same errors. - OpenSearch 2 and 3 (2.61.0-beta.5). Install
kuzzle-storage-opensearch-2(OpenSearch 2.19 and later 2.x) orkuzzle-storage-opensearch-3(OpenSearch 3) next to Kuzzle and name it inservices.storageEngine.driver. Both are Kuzzle's Elasticsearch 7 driver on the OpenSearch client: same mappings, same queries, same errors. They do not move your data: copy it from Elasticsearch with a snapshot or a remote reindex. majorVersionis deprecated, in the documentation only: it keeps working unchanged in Kuzzle 2, and Kuzzle 3 will select the storage engine withdriveralone. Kuzzle warns at startup only if your configuration sets bothdriverandmajorVersion, sincemajorVersionis then ignored.- Clearer storage driver errors. A missing driver says how to install it, without Node's whole
Require stack; an installed package that is not a usable driver (such as a name-reservation placeholder) says so;majorVersion: "9"without a driver stops Kuzzle withservices.storage_driver.unsupported_major_version, which points toservices.storageEngine.driver; the startup log names the directory the driver was loaded from (#3134). - Driver names.
services.storageEngine.driveraccepts an npm alias, and a driver installed withnpm linkor from a directory now works. A path is refused, with a hint to install the package and name it (#3142). - Which storage engine Kuzzle runs on (2.61.0-beta.6). Plugins and applications can ask it with
context.accessors.getStorageEngine()orapp.storage.getEngine(): the driver package, the engine family (elasticsearch,opensearch) and the engine server's version. Use it instead of guessing the engine frommajorVersion(#3133). - Storage connections closed on shutdown (2.61.0-beta.6). A driver can implement an optional
close()hook, which Kuzzle calls on a graceful shutdown to release its engine connections; every official driver does. If it fails, Kuzzle logs a warning and carries on shutting down (#3141). Since 2.61.0-beta.7, Kuzzle also waits for the requests plugins are running before closing the storage: in 2.61.0-beta.6, stopping Kuzzle right after it started could make it exit with code 1, in development mode, when a plugin was still working at startup (#3160). - Engine-neutral messages (2.61.0-beta.6). Storage error messages and logs say "storage engine" instead of "Elasticsearch", which was wrong on OpenSearch. Error ids and codes do not change (#3143).
- For driver authors.
kuzzleexports what a driver needs: theStorageDrivercontract and its types, a conformance kit (describeStorageDriverConformance) that tests a driver against its real engine, andstorageError, so that a driver returns the same errors as Kuzzle. Read the new Write storage drivers guide. - Drivers documentation. Each official driver has its own documentation (install, configuration, TypeScript, compatibility, troubleshooting) in the new Drivers section.
What's fixed #
- A node joining a cluster could still list an index or a collection that another node had deleted before it joined, and keep a collection lock that was already released. It now replaces its cache with what the storage holds when it loads it.
- In a cluster, a request served by one node right after another node created an index or a collection could fail with
services.storage.unknown_indexorunknown_collection, or not see it in a list, for a few milliseconds. Likewise, creating an index another node had just deleted could fail withindex_already_exists. A node now checks the storage before answering so. Those checks start at most once everyservices.storageEngine.cacheMissReadInterval(default 100 ms,0to check on every miss), so a request on a missing index or collection can fail up to 100 ms later (#3140). - If the
kuzzle-storage-es-7orkuzzle-storage-es-8package was missing fromnode_modules, Kuzzle stopped with a rawCannot find moduleerror (2.61.0-beta.2). It now stops with the documentedservices.storage_driver.not_founderror, as for an external driver (2.61.0-beta.3). - An external driver could load another copy of
kuzzlethan the running one, when Kuzzle runs as its own application, as in the official Docker image: some documented404or400errors then came back as500unexpected_error. A driver now always uses the Kuzzle that loads it (#3132). - Some storage engine errors reached clients as
services.storage.unexpected_bad_requestorunexpected_errorinstead of their documented code, since before 2.61: the error mapping expected messages the current engine clients no longer produce. With every official driver, they now come back astoo_many_operations(thread pool or indexing pressure rejection),cannot_change_mapping,unexpected_properties,invalid_mapping_type,too_many_changes(version conflict) andunknown_query_keyword. - A driver now refuses to start on an engine it does not support: an Elasticsearch driver on another Elasticsearch major (e.g.
kuzzle-storage-es-7on an 8.x cluster) or on OpenSearch, which reports itself as Elasticsearch 7.10.2. The OpenSearch drivers name OpenSearch, not Elasticsearch, in their logs and messages. - A driver missing a method of the storage contract started, then failed with a
500on the first request using it. Kuzzle now refuses it at startup withservices.storage_driver.invalid_driver(#3137). - An unhandled rejection whose reason is not an
Errorwas logged asERROR: unhandledRejection: [object Object], or[object Promise]with no reason at all. The log now shows the reason's content, or the promise's (2.61.0-beta.9).
Under the hood #
kuzzledepends onkuzzle-storage-es-7andkuzzle-storage-es-8at pinned versions: a new version of a built-in driver reaches you with a Kuzzle release.- All five official drivers have stable releases (2.61.0-beta.8):
npm install kuzzle-storage-es-9,kuzzle-storage-opensearch-2orkuzzle-storage-opensearch-3installs a release, no beta tag needed, and Kuzzle's built-in drivers are their stable releases too. - Dependency updates (2.61.0-beta.6):
lodash4.18.1 (security fixes: prototype pollution in_.unset/_.omit, injection in_.templateimports),uuid14,zeromq6.8.0, and patch or minor updates ofeventemitter3,moment,pino-pretty,semver,validatorandyargs. No change in behavior.