← Back to Changelog

v6.1.0

Release

[email protected] — 2026-10-06

First stable release of Keyv v6, published to npm's latest tag.

All 20 published packages release in lockstep at 6.1.0; there is no 6.0.0. @keyv/website is private and not published.

Coming from v5? Follow the v5 to v6 migration guide, or point your coding agent at https://keyv.org/skills/migrate. v5 stays in maintenance; install it with keyv@5.

⚠ BREAKING CHANGES

These are changes since 6.0.0-rc.1. Coming from v5, start with the migration guide.

  • keyv, adapters: the namespace separator option is namespaceSeparator on every adapter that joins the namespace and the key, and it defaults to ::; keySeparator and keyPrefixSeparator are gone (d0bc310, #2189) Migration from rc.1: rename the option. To keep reading namespaced data rc.1 wrote, set namespaceSeparator: ':' on the memory and bridge adapters, @keyv/etcd, @keyv/dynamo, @keyv/cloudflare-kv and @keyv/valkey. @keyv/redis already used :: in rc.1. Migration from v5: v5's Keyv also prefixed every key with <namespace>:, so the setting depends on the adapter. A default v5 @keyv/redis setup stored keyv::keyv:foo, which v6 reads with new Keyv(new KeyvRedis(uri, { namespaceSeparator: '::keyv:' }), { namespace: 'keyv' }). If you used createKeyv(), set only the same namespace. For other adapters, see The Default keyv Namespace Was Removed.
  • keyv: throwOnErrors is removed; a failed call returns a fallback value when an error listener is attached and rejects when none is (860dba7, #2155) Migration: remove throwOnErrors, and attach an error listener if you want fallback values instead of rejections.
  • keyv: a namespace set on the storage adapter is used when Keyv has none (c6e88e7, #2156) Migration: data rc.1 wrote in that setup has no namespace; remove the adapter's namespace to keep reading it, or let it refill.
  • keyv: a namespaced clear() fails instead of wiping a store it can't list (790eb3c, #2186) Migration: give the store keys() or iterator(), or call clear() on a Keyv instance without a namespace to empty it.
  • keyv: writes fail when an encryption adapter is set and serialization is off; rc.1 stored those values unencrypted (b73ee16, #2176) Migration: keep serialization on, which is the default, when you use encryption.
  • postgres, sqlite, mongo, dynamo, cloudflare-kv, etcd: keys that start with <namespace>: are stored as given instead of being treated as already prefixed (9dec04c, #2159) Migration: entries rc.1 wrote under such keys read as missing; write them again.
  • encrypt-node, encrypt-web: @keyv/encrypt-node accepts only AES-GCM, AES-CCM and ChaCha20-Poly1305 with base64, base64url or hex output, and @keyv/encrypt-web accepts only AES-GCM; AES-CBC is removed (b06ec8b, #2187) Migration: the defaults are unchanged; re-encrypt values written with any other algorithm or encoding before you upgrade.
  • dynamo: keys written without a TTL no longer expire, and sixHoursInMilliseconds is removed (476761d, #2161) Migration: set Keyv's ttl option for a default expiry, as in new Keyv(store, { ttl: 6 * 60 * 60 * 1000 }).
  • etcd: the lease property is removed, and the store ttl applies to each key from its own write (6ba3096, #2160) Migration: remove code that reads or sets store.lease.
  • etcd: without a namespace, clear() and iterator() only touch entries Keyv wrote without a namespace (8a77946, #2173) Migration: set noNamespaceAffectsAll: true for the rc.1 behavior, and namespaceSeparator: ':' while etcd still holds namespaced rc.1 entries.
  • memcache: clear() only removes the store's own entries, and values rc.1 wrote read as missing (12415c5, #2179) Migration: let the cache refill; set noNamespaceAffectsAll: true on a store without a namespace to flush the whole server.
  • bigmap: setting storeSize keeps every entry and no longer emits clear (b80b44d, #2178) Migration: call clear() yourself if you resized the map to empty it.

Features

  • add the keyv-migrate agent skill, which upgrades a project from Keyv v4 or v5 to v6; it is published at https://keyv.org/skills/migrate (bae30d5, #2171)

    npx skills add jaredwray/keyv --skill keyv-migrate
    
  • add a namespaceSeparator option to every adapter that joins the namespace and the key; it defaults to :: (d0bc310, #2189)

    import Keyv from 'keyv';
    import KeyvEtcd from '@keyv/etcd';
    
    // Read keys written with the old ':' separator
    const keyv = new Keyv(new KeyvEtcd('etcd://localhost:2379', { namespaceSeparator: ':' }), { namespace: 'keyv' });
    

Bug Fixes

  • keyv: promise-based stores without async methods go through KeyvBridgeAdapter (9c82ca3, #2157)
  • keyv: the sanitizer strips patterns until none remain (3462350, #2158)
  • keyv, postgres: fractional TTLs no longer fail writes, and postgres disconnect() releases the pool it connected with (82daf5d, #2168)
  • postgres, sqlite: a clearExpiredInterval over 24.8 days no longer runs cleanup every millisecond (920ad81, #2164)
  • cloudflare-kv: keys with a TTL of 60 seconds or less are removed by KV (ce6efce, #2162)
  • etcd: the value envelope uses Keyv's JSON serializer, so Buffer and BigInt values round-trip (9010961, #2041)
  • etcd: setMany() reports failed writes as false (c8133f7, #2172)
  • memcache: keys memcached can't store now work, and rejected writes return false (365eeba, #2174)
  • mongo: add a v6 migration script so documents v5 wrote stay readable (4068b0a, #2152)
  • mongo: GridFS reads the newest revision, and delete() removes every revision (8101af5, #2163)
  • mysql: tables get a primary key on (namespace, id), and existing tables are migrated on connect (1bb5d90, #2165)
  • mysql: the primary-key migration keeps primary keys you added and finds generated invisible ones (fbbb044, #2170)
  • mysql, postgres: the v6 migration scripts ship in the package and run with npx tsx (8ede7f4, #2150)
  • mysql, valkey: keyv is a peer dependency instead of a bundled copy (2c72abe, #2149)
  • postgres: the migration script drops the legacy primary key first, deleteMany() runs as one statement, and SQL NULL reads as undefined (aa692eb, #2064)
  • redis: createKeyv() accepts cluster and sentinel options, replacing the client removes the old client's listeners, and missing values are undefined (cab81d2, #2062)
  • redis: concurrent operations during the handshake share one connect instead of failing (bb35d2b, #2105)
  • redis: connectionTimeout covers the handshake, and timed-out connects close their sockets (00a48ba, #2108)
  • redis: createKeyvNonBlocking() stops reconnecting to a server that is down (0575171, #2167)
  • redis: clear() and iterator() match the namespace literally, not as a glob pattern (b91b8bf, #2185)
  • sqlite: converting a v5 table runs in a transaction, and the sqlite3 driver no longer hangs after a failed statement (90630ee, #2063)
  • valkey: reads return undefined, never null (2435715, #2065)
  • valkey: clear() removes only its own namespace, not namespaces that share its prefix (4d369be, #2147)
  • valkey: clear(), iterator() and useSets work in cluster mode (a4326e9, #2166)

Documentation

  • keyv.org moves to the Docula modern template, and the v5 docs are archived at https://keyv.org/v5/ (52f692d, #2066)
  • how to keep reading data written by v5, with each adapter's stored key layout (df63ef6, #2151)
  • encryption: use a random secret as the key, or derive one with PBKDF2 (b5eeec9, #2188)
  • postgres, redis: TLS how-tos for Amazon RDS for PostgreSQL and Redis Cloud (bda7916, #2194)
  • migration guide and skill corrections (13c683e, #2169; f1bb9e3, #2175; bec33f4, #2177)

Internal

  • npm releases are staged and approved with 2FA, with provenance and an Aikido scan gate; stable v6 releases stage under latest (#2057, #2124, #2148)
  • runtime dependency upgrades: @redis/client 6.2.1, mongodb 7.6.0, mysql2 3.24.2, pg 8.23.0, better-sqlite3 13.0.3, memcache 1.10.0, AWS SDK DynamoDB 3.1121.0, msgpackr 2.1.0, lz4-napi 2.10.0, hookified 3.0.3 (#2083–#2092)

Contributors

  • @jaredwray (99)

Full List of Changes

  • etcd - fix: Use Keyv default serializer for value envelope by @jaredwray in #2041
  • mono - chore: defense - stage npm publishes with Aikido gate by @jaredwray in #2057
  • website - docs: migrate to Docula 2 modern template and archive v5 by @jaredwray in #2066
  • redis - refactor: v6 client swap, API docs, and test uniformity by @jaredwray in #2062
  • postgres - fix: v6 release review (migration, API docs, events) by @jaredwray in #2064
  • sqlite - fix: harden v6 sqlite adapter, docs, and tests by @jaredwray in #2063
  • valkey - refactor: v6 review cleanup for docs, tests, and events by @jaredwray in #2065
  • redis - fix: share in-flight connect so concurrent ops are not dropped by @jaredwray in #2105
  • redis - fix: Abort timed-out Redis connects without leaking sockets by @jaredwray in #2108
  • mono - chore: release concurrency group + v5 staged publishing docs by @jaredwray in #2124
  • valkey - fix: clear() only removes keys in the exact namespace by @jaredwray in #2147
  • mono - fix: stage stable v6 releases under latest, not v6-lts by @jaredwray in #2148
  • mono - fix: declare keyv as a peer dependency of mysql and valkey by @jaredwray in #2149
  • mono - fix: make the mysql and postgres v6 migration scripts runnable by @jaredwray in #2150
  • mono - docs: explain how to keep reading data written by v5 by @jaredwray in #2151
  • mongo - fix: add a v6 migration script so v5 documents stay readable by @jaredwray in #2152
  • keyv - fix: follow the EventEmitter error rule and remove throwOnErrors by @jaredwray in #2155
  • keyv - fix: keep a namespace set on the storage adapter by @jaredwray in #2156
  • keyv - fix: route promise-based stores without async methods through the bridge by @jaredwray in #2157
  • keyv - fix: strip sanitizer patterns until none remain by @jaredwray in #2158
  • mono - fix: keys that start with the namespace no longer collide by @jaredwray in #2159
  • etcd - fix: default ttl applies per key and keeps working after the first lease expires by @jaredwray in #2160
  • dynamo - fix: clear() removes every scan page and keys without a ttl no longer expire by @jaredwray in #2161
  • cloudflare-kv - fix: keys with a ttl of 60 seconds or less are removed by KV by @jaredwray in #2162
  • mongo - fix: GridFS reads the newest value and delete removes every revision by @jaredwray in #2163
  • mono - fix: a clearExpiredInterval over 24.8 days no longer runs cleanup every millisecond by @jaredwray in #2164
  • mysql - fix: tables get a primary key on (namespace, id) by @jaredwray in #2165
  • valkey - fix: clear, iterator and useSets work in cluster mode by @jaredwray in #2166
  • redis - fix: createKeyvNonBlocking stops reconnecting, and failed connects stop adding listeners by @jaredwray in #2167
  • mono - fix: fractional TTLs no longer fail writes, and postgres disconnect releases the pool it connected with by @jaredwray in #2168
  • mono - docs: drop the removed useKeyPrefix option from dynamo and cloudflare-kv examples by @jaredwray in #2169
  • mysql - fix: Primary key migration keeps owner keys, replaces prefix keys, and finds hidden generated keys by @jaredwray in #2170
  • etcd - fix: setMany reports failed writes as false by @jaredwray in #2172
  • etcd - fix: Without a namespace, clear() and iterator() only touch Keyv's own entries by @jaredwray in #2173
  • mono - feat: Add keyv-migrate agent skill at keyv.org/skills/migrate and fix stale v6 docs by @jaredwray in #2171
  • memcache - fix: Keys memcached can't store now work, and rejected writes return false by @jaredwray in #2174
  • mono - docs: Correct old delete results and etcd clear() in the migration skill by @jaredwray in #2175
  • keyv - fix: writes fail with an error when encryption is set without serialization by @jaredwray in #2176
  • skills - docs: bound the Redis "every key" range to @keyv/redis 2.7 through 3.0 by @jaredwray in #2177
  • bigmap - fix: Changing storeSize or storeHashFunction keeps every entry by @jaredwray in #2178
  • memcache - fix: clear() only removes the store's own entries by @jaredwray in #2179
  • redis - fix: clear() and iterator() match the namespace literally by @jaredwray in #2185
  • keyv - fix: a namespaced clear() fails instead of wiping a store it can't scope by @jaredwray in #2186
  • mono - fix: authenticated ciphers only, bridge setMany() results, serializer __proto__ by @jaredwray in #2187
  • mono - docs: use a random secret as the encryption key, or derive one with PBKDF2 by @jaredwray in #2188
  • mono - feat: namespaceSeparator on every adapter, defaulting to :: by @jaredwray in #2189
  • mono - docs: Amazon RDS for PostgreSQL and Redis Cloud how-tos by @jaredwray in #2194
  • mono - chore: Release v6.1.0 by @jaredwray in #2192
  • …plus 51 dependency, tooling, CI, test and repo-maintenance PRs; see the full diff.

Full diff: https://github.com/jaredwray/keyv/compare/v6.0.0-rc.1...v6.1.0