Skip to content

Releases: jaredwray/keyv

v6.0.0-beta.3

11 Jun 20:24
5414c14

Choose a tag to compare

Keyv v6.0.0-beta.3

This release rolls up the entire v6 beta cycle — everything merged since v6.0.0-alpha.3. v6 is a major, ground-up modernization of Keyv: a leaner core, a new raw-data API, first-class capability detection, telemetry, two new encryption packages, a dependency-free etcd adapter, and a wave of breaking dependency upgrades across the monorepo.

Heads up: v6 contains a number of breaking changes vs. v5. If you are upgrading from v5, read the v5 → v6 migration guide alongside these notes.


Highlights

  • 🔐 Two new encryption packages@keyv/encrypt-node (Node.js crypto) and @keyv/encrypt-web (Web Crypto API), with a shared wire format so they're cross-compatible.
  • 🧩 Raw data APIgetRaw / getManyRaw / setRaw / setManyRaw for working directly with the stored { value, expires } envelope.
  • 🔎 Capability detectiondetectKeyv, detectKeyvStorage, detectKeyvCompression, detectKeyvSerialization, detectKeyvEncryption helpers.
  • 📊 Stats / telemetry overhaul — aggregate counters plus LRU-bounded per-key frequency maps.
  • 🧼 Key sanitization — opt-in protection against SQL/Mongo/path-traversal/control-character injection in keys and namespaces.
  • 🪝 Hookified everywhere — unified events + pre/post hooks across the core and every adapter, now including setMany, deleteMany, clear, and disconnect.
  • 🌐 Dependency-free etcd adapter — talks to etcd v3 over its HTTP/JSON gateway via an in-house client (no etcd3).
  • ⚙️ Optional serialization and no key-prefixing in core for a smaller, faster default path.
  • 🏗️ Build & toolchain modernization — moved to tsdown, TypeScript 6, and a refreshed release pipeline (OIDC publishing).
  • 📦 Major dependency upgrades across Redis, MongoDB, MySQL, Postgres, DynamoDB, msgpackr, hookified, hashery, and more.

⚠️ Breaking Changes

Core

  • StoredData and StoredDataRaw types removed. Use the KeyvValue<T> envelope ({ value, expires? }) and the new raw API instead. (#1929)
  • Keys are no longer prefixed in core. Namespacing/prefixing is now handled by the storage adapters that need it, not the core. (#1899)
  • get no longer checks expiry by default. Expiration is evaluated lazily/where appropriate to keep the hot path fast; expired entries still resolve to undefined through the normal read paths. To re-enable core-level expiry checks, set the checkExpired: true option. (#1923)
  • Moved to Hookified for events + hooks. Replaces the old EventEmitter base across core and adapters. (#1900)
  • .set() now returns a boolean instead of the instance. (#1904)
  • Iterator API simplified and various method signatures cleaned up. (#1902)
  • setRaw / setManyRaw no longer take a ttl argument — set expires on the value envelope instead. (#1905)
  • opts removed from KeyvStorageAdapter and the opts property removed from the Keyv class. (#1906)

Adapters & tooling (dependency bumps that change minimums)

  • @redis/client upgraded to v6 (breaking). (#1954)
  • hookified upgraded to v3 (breaking) across the monorepo. (#1957)
  • hashery upgraded to v2 in BigMap (breaking). (#1956)
  • msgpackr upgraded to v2 in @keyv/serialize-msgpackr (breaking). (#1958)
  • bignumber.js upgraded to v11 in the test-suite (breaking). (#1955)
  • docula upgraded to v2 for the website (breaking). (#1947)
  • Code-quality deps, GitHub Actions, and build tooling upgraded (some breaking minimum versions). (#1944, #1946, #1945)
  • TypeScript 6 is now used to build the monorepo. (#1933)
  • test-suite v6 overhaul — compliance tests rewritten for the v6 API. If you maintain a third-party adapter against @keyv/test-suite, expect changes. (#1931)

🔐 New: Encryption Packages

Two new adapters let you encrypt values transparently. They share a wire format, so data written by one can be read by the other (same key + algorithm).

@keyv/encrypt-node — Node.js crypto

Supports AES-GCM (default), AES-CCM, ChaCha20-Poly1305, AES-CBC, and any cipher available in your Node install. (#1927)

import Keyv from 'keyv';
import KeyvEncryptNode from '@keyv/encrypt-node';

const encryption = new KeyvEncryptNode({ key: 'your-secret-key' });
const keyv = new Keyv({ encryption });

await keyv.set('foo', 'bar');
const value = await keyv.get('foo'); // 'bar' (decrypted automatically)
// Pick an algorithm and output encoding
const encryption = new KeyvEncryptNode({
  key: 'your-secret-key',
  algorithm: 'chacha20-poly1305',
  encoding: 'hex',
});

@keyv/encrypt-web — Web Crypto API

Works in browsers, Deno, Cloudflare Workers, and Node.js 18+ with no Node-specific dependencies. Supports AES-GCM (recommended) and AES-CBC. (#1928)

import Keyv from 'keyv';
import KeyvEncryptWeb from '@keyv/encrypt-web';

const encryption = new KeyvEncryptWeb({ key: 'your-secret-key' });
const keyv = new Keyv({ encryption });

await keyv.set('foo', 'bar');
const value = await keyv.get('foo'); // 'bar'

Cross-compatibility wire format (same for both packages):

  • AES-GCM: base64([IV (12 bytes) || AuthTag (16 bytes) || Ciphertext])
  • AES-CBC: base64([IV (16 bytes) || Ciphertext])

🧩 Core: Raw Data API

Work directly with the stored envelope ({ value, expires? }) — useful for replication, cache warming, and moving data between stores. (#1897, #1929)

import Keyv from 'keyv';
const keyv = new Keyv();

// Write a raw envelope with an absolute expiry timestamp
await keyv.setRaw('foo', { value: 'bar', expires: Date.now() + 60_000 });

// No expiry
await keyv.setRaw('foo', { value: 'bar' });

// Read the raw envelope back
const raw = await keyv.getRaw('foo'); // { value: 'bar', expires: 1234567890 }

// Copy between instances without unwrapping/rewrapping
if (raw) {
  await other.setRaw('foo', raw);
}

// Batch variants
await keyv.setManyRaw([
  { key: 'a', value: { value: 1 } },
  { key: 'b', value: { value: 2, expires: Date.now() + 60_000 } },
]);
const many = await keyv.getManyRaw(['a', 'b']);

The store-level TTL is derived automatically from value.expires, so you no longer pass a separate ttl to the raw setters.


🔎 Core: Capability Detection

New helpers report exactly which parts of an interface an object implements. Each returns a compatible flag — true only when the full interface is satisfied — plus a methods map describing whether each method exists and its methodType ("sync" / "async" / "none"). (#1909, #1930)

import Keyv, {
  detectKeyv,
  detectKeyvStorage,
  detectKeyvCompression,
  detectKeyvSerialization,
  detectKeyvEncryption,
} from 'keyv';

detectKeyv(new Keyv()).compatible; // true (only when ALL capabilities are present)
detectKeyv(new Map()).compatible;  // false — but methods.get.exists is still true

// Storage detection reports the detected store type plus sync/async per method
const r = detectKeyvStorage(new Map());
r.compatible;             // true
r.store;                  // "mapLike"  ("keyvStorage" | "mapLike" | "asyncMap" | "none")
r.methods.get.methodType; // "sync"

detectKeyvSerialization(JSON).compatible;                                    // true
detectKeyvCompression({ compress: d => d, decompress: d => d }).compatible;  // true
detectKeyvEncryption({ encrypt: d => d, decrypt: d => d }).compatible;       // true

📊 Core: Stats / Telemetry

Opt-in statistics with aggregate counters and LRU-bounded per-key frequency maps. (#1912)

const keyv = new Keyv({ stats: true });

await keyv.set('foo', 'bar');
await keyv.get('foo');          // hit
await keyv.get('nonexistent');  // miss
await keyv.delete('foo');

keyv.stats.hits;    // 1
keyv.stats.misses;  // 1
keyv.stats.sets;    // 1
keyv.stats.deletes; // 1

// Per-key frequency (each map capped at maxEntries, default 1000)
keyv.stats.hitKeys.get('foo');           // 1
keyv.stats.missKeys.get('nonexistent');  // 1

keyv.stats.reset();          // clears counters and maps
keyv.stats.enabled = false;  // disable at runtime (auto-unsubscribes)

🧼 Core: Key Sanitization

Opt-in detection that strips dangerous patterns (not harmless characters) from keys and namespaces — guarding against SQL injection, MongoDB operator injection, path traversal, and control-character/CRLF attacks. Results are LRU-cached for speed.

const keyv = new Keyv({ sanitize: true });
// or fine-grained:
const keyv2 = new Keyv({ sanitize: { sql: true, mongo: true, path: true, escape: true } });

Applied to every key-accepting method (get, set, delete, has, the *Many variants, and the raw variants), plus namespaces at construction and on the namespace setter.


🪝 Core: Events, Hooks & Error Handling

  • Hooks for more operations — added pre/post hooks for setMany, deleteMany, clear, and disconnect, in addition to the existing single-key hooks. (#1918, #1924)

  • throwOnErrors — make operations throw instead of emitting 'error', so you can try/catch (great with @keyv/redis connection handling). (#1910)

    import Keyv from 'keyv';
    import KeyvRedis from '@keyv/redis';
    
    const keyv = new Keyv({ store: new KeyvRedis('redis://localhost:6379'), throwOnErrors: true });
    try {
      await keyv.set('foo', 'bar');
    } catch (error) {
      // handle connection/timeout errors yourself
    }
  • Key prefixing moved to adapters. Prefixing/namespacing is now handled by the storage adapters that need it rather than the core. (#1899)

  • Encode/decode now propagate errors instead of swallowing ...

Read more

v6.0.0-beta.1

01 Apr 20:28

Choose a tag to compare

What's Changed

  • keyv - feat (breaking) stats / telemetry overhaul by @jaredwray in #1912
  • keyv - feat: (breaking) memory adapter, bridge adapter, keyv overhaul by @jaredwray in #1913
  • bigmap - feat: Optimize BigMap hash function and hot path performance by @jaredwray in #1915
  • dynamo - feat: Add disconnect and iterator methods to KeyvDynamo by @jaredwray in #1914
  • keyv - fix: handling has and hasMany better by @jaredwray in #1916
  • keyv - fix: adding in decode expiring to has by @jaredwray in #1917
  • keyv - feat: adding hooks for setMany and deleteMany by @jaredwray in #1918
  • keyv - fix: dead code on getManyRaw by @jaredwray in #1919
  • keyv - fix: on set with no result do not send telemetry STAT_SET by @jaredwray in #1920
  • keyv - fix: telemetry issue on setRaw by @jaredwray in #1921
  • keyv - fix: having encode / decode propegate errors by @jaredwray in #1922
  • keyv - feat: (breaking) by default keyv no longer checks expires by @jaredwray in #1923
  • keyv - feat: adding in hooks for clear and disconnect by @jaredwray in #1924
  • keyv - fix: minor bug fixes on memory, ttl, etc by @jaredwray in #1925
  • mono - feat: moving to tsdown for build by @jaredwray in #1926
  • encryption-node - feat: Add Node.js encryption adapter for Keyv by @jaredwray in #1927
  • encrypt-web - feat: adding new web crypto module by @jaredwray in #1928
  • keyv - feat: (breaking) removing StoredData and StoredDataRaw types by @jaredwray in #1929
  • keyv - feat: enhancing capabilities by @jaredwray in #1930
  • test-suite - feat (breaking) overhaul based on v6 changes by @jaredwray in #1931

Full Changelog: v6.0.0-alpha.4...v6.0.0-beta.1

v6.0.0-alpha.4

27 Mar 06:38

Choose a tag to compare

What's Changed

  • keyv - feat: (breaking) moving to Hookified by @jaredwray in #1900
  • compression - feat: moving to KeyvCompressionAdapter standard by @jaredwray in #1901
  • keyv - feat: (breaking) api changes and iterator simplification by @jaredwray in #1902
  • keyv - feat: moving storage setMany to use KeyvEntry by @jaredwray in #1903
  • keyv - feat: (breaking) moving to boolean return on set by @jaredwray in #1904
  • keyv - fix: (breaking) setRaw and setMany raw do not need ttl param by @jaredwray in #1905
  • keyv - feat: (breaking) removing opts from KeyvStorageAdapter by @jaredwray in #1906
  • keyv - feat: browser compatability by @jaredwray in #1907
  • keyv - fix: updating checks for browser tests by @jaredwray in #1908
  • feat: updating capability helper functions by @jaredwray in #1909
  • keyv - feat: clean up of code with fixes and helpers by @jaredwray in #1910

Full Changelog: v6.0.0-alpha.3...v6.0.0-alpha.4

v6.0.0-alpha.3

22 Mar 21:09

Choose a tag to compare

What's Changed

Full Changelog: v6.0.0-alpha.2...v6.0.0-alpha.3

v6.0.0-alpha.2

04 Mar 02:56

Choose a tag to compare

What's Changed

Full Changelog: 6.0.0-alpha.1...v6.0.0-alpha.2

6.0.0-alpha.1

26 Feb 01:35
d7419cf

Choose a tag to compare

What's Changed

  • redis - feat: exporting RedisSentinelOptions by @jaredwray in #1823
  • redis - feat: exporting redis sentinel options with updated documentation by @jaredwray in #1824
  • mono - chore: upgrading vitest to 4.0.18 by @jaredwray in #1827
  • keyv - chore: upgrading vitest and supporting modules to latest by @jaredwray in #1828
  • serialize - chore: upgrading vitest to 4.0.18 and supporting packages by @jaredwray in #1829
  • sqlite - feat: Add WAL (Write-Ahead Logging) mode support by @snomiao in #1826
  • compress-brotli - chore: upgrading vitest to 4.0.18 by @jaredwray in #1830
  • compress-gzip - chore: upgrading vitest to 4.0.18 by @jaredwray in #1831
  • sqlite - feat: Add warning for WAL mode with in-memory SQLite databases by @jaredwray in #1832
  • docs: Add v5 to v6 migration guide by @jaredwray in #1833
  • memcache - docs: Add memjs to memcache migration to v5-to-v6 guide by @jaredwray in #1836
  • mono - chore: moving keyv to better mono structure by @jaredwray in #1838
  • mono - feat: adding in version sync across all packages by @jaredwray in #1839
  • mono - fix: tsconfig moving to esnext by @jaredwray in #1840
  • compress-brotli - feat: moving to native zlib brotli engine by @jaredwray in #1841
  • mono - refactor: remove ttlSupport property from all storage adapters by @jaredwray in #1842
  • keyv - refactor: remove opts property from Keyv class by @jaredwray in #1843
  • keyv - chore: remove cyclic workspace dependencies by @jaredwray in #1844
  • keyv - chore: adding tests for code coverage by @jaredwray in #1845
  • memcache - feat: migrating from memjs to memcache by @jaredwray in #1846
  • memcache - feat: adding in createKeyv helper function by @jaredwray in #1847
  • memcache - fix: removing serialization as not needed by @jaredwray in #1848
  • memcache - feat: (breaking) moving to nodes based on memcache options by @jaredwray in #1849
  • memcache - feat: moving eventemitter to hookified by @jaredwray in #1850
  • memcache - feat: adding constructor documentation by @jaredwray in #1851
  • keyv - docs: Move Bun Support section lower in README by @jaredwray in #1853
  • postgres - feat: adding in table of contents by @jaredwray in #1856
  • postgres - feat: migrating to hookified and advanced functions by @jaredwray in #1857
  • postgres - feat: moving to properties by @jaredwray in #1858
  • postgres - feat: adding in native namespace support by @jaredwray in #1860
  • postgres - feat: better ttl support by @jaredwray in #1861
  • mysql - chore: adding table of contents by @jaredwray in #1862
  • mysql - feat: adding setMany and hasMany by @jaredwray in #1863
  • mysql - feat: moving to native namespacing by @jaredwray in #1864
  • mysql - feat: removing dialect as no longer needed by @jaredwray in #1865
  • mysql - feat: (breaking) moving from keySize to keyLength by @jaredwray in #1866
  • mysql - feat: moving from eventemitter to hookified by @jaredwray in #1867
  • mysql - feat: createKeyv helper and options cleanup by @jaredwray in #1868
  • mongo - feat: migrating to hookified from eventemitter by @jaredwray in #1869
  • mongo - feat: adding createKeyv helper by @jaredwray in #1871
  • mongo - feat: moving to more robust options and properties by @jaredwray in #1872
  • mongo - fix: moving gridFS property to read only by @jaredwray in #1873
  • mongo - feat: adding hasMany and setMany by @jaredwray in #1874
  • mono - feat: adding in release action by @jaredwray in #1875

New Contributors

Full Changelog: 2026-01-20...6.0.0-alpha.1

2026-01-20

21 Jan 00:37

Choose a tag to compare

What's Changed

Full Changelog: 2025-12-26...2025-01-20

2025-12-26

26 Dec 22:36

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: 2025-12-10...2025-12-26

2025-12-10

10 Dec 18:04
0d66fc9

Choose a tag to compare

What's Changed

Full Changelog: 2025-11-20...2025-12-10

2025-11-20

21 Nov 07:35
3059ec2

Choose a tag to compare

What's Changed

Full Changelog: 2025-11-17...2025-11-20