NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #189 most downloaded on npm
Simple key-value storage with support for multiple backends
Last release 2 months ago
03 Aug 2026
Ships fairly regularly
a new release about every 5 weeks
No release notes found
nothing matched a version
Nothing withdrawn
no release was ever pulled
9 years old
85 releases · first in 2017
Promote 6.0 to release candidate: Cloudflare KV adapter, MySQL fixes, and a full dependency refresh.
Promote 6.0 to release candidate: Cloudflare KV adapter, MySQL fixes, and a full dependency refresh.
All published @keyv/* adapters release in lockstep at this version. @keyv/website is private and not published.
VARBINARY (6e519b4, #2015; f579073, #2016)@keyv/mysql tables created under 6.0.0-beta.4 use the previous key column type. Recreate the keyv table, or ALTER the key column to VARBINARY, before upgrading.checkExpired now defaults to true (f067213, #1984)checkExpired: false to restore the previous behavior.removeKeyPrefix behavior for v6 (73fd79b, #2013)add Cloudflare Workers KV storage adapter (e004467, #1985)
import { createKeyv } from "@keyv/cloudflare-kv";
// REST mode — from any Node.js process
const keyv = createKeyv({
mode: "rest",
accountId: process.env.CF_ACCOUNT_ID,
namespaceId: process.env.CF_KV_NAMESPACE_ID,
apiToken: process.env.CF_API_TOKEN,
});
// Or "bind" mode inside a Worker: createKeyv({ kvNamespace: env.MY_KV })keyv: add the built-in adapters to the docs (2e03276, #1983)
KeyvAny/KeyvAnyArray types and replace explicit any (49ed583, #2010)prebuild-install), mongodb 7.4→7.5, mysql2 3.22→3.23, iovalkey 0.3→0.4, @redis/client 6.0→6.1, hookified 3.0.1→3.0.2, actions/setup-node v6→v7, and the Node engines floor raised to ≥ 22.19.0. Full inventory below.Full diff: v6.0.0-beta.4...v6.0.0-rc.1
One column per quarter.
Keyv v6.0.0-beta.4 — 2026-06-18
Finalize the v6 storage-adapter API (ttl → expires) and complete the cross-adapter code/test review.
expires (absolute epoch-ms timestamp) instead of a relative ttl. (da9c08f, #1981)expires value from the entry envelope instead of accepting a ttl argument. The Keyv core API is unchanged — it continues to derive expires from the value envelope, so typical keyv.set(key, value, ttl) usage is unaffected.bigmap: wire up Hookified events — BigMap now emits SET, DELETE, and CLEAR via the new BigMapEvents enum. (b88d03f, #1977)
import { BigMap, BigMapEvents } from '@keyv/bigmap';
const map = new BigMap<string>();
map.on(BigMapEvents.SET, (key, value) => console.log('set', key, value));
map.on(BigMapEvents.DELETE, (key) => console.log('deleted', key));
map.set('a', '1'); // → "set a 1"
map.delete('a'); // → "deleted a"Also renames the exported MapInterfacee type to MapInterface (typo fix — safe within the v6 beta).
undefined for missing values and align tests/docs. (1e84580, #1966)undefined instead of null, guard getMany, and align tests/docs. (d76926b, #1969)@keyv/postgres. (9fa6847, #1971)Full diff: v6.0.0-beta.3...v6.0.0-beta.4
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.
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.
@keyv/encrypt-node (Node.js crypto) and @keyv/encrypt-web (Web Crypto API), with a shared wire format so they're cross-compatible.getRaw / getManyRaw / setRaw / setManyRaw for working directly with the stored { value, expires } envelope.detectKeyv, detectKeyvStorage, detectKeyvCompression, detectKeyvSerialization, detectKeyvEncryption helpers.setMany, deleteMany, clear, and disconnect.etcd3).tsdown, TypeScript 6, and a refreshed release pipeline (OIDC publishing).StoredData and StoredDataRaw types removed. Use the KeyvValue<T> envelope ({ value, expires? }) and the new raw API instead. (#1929)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)EventEmitter base across core and adapters. (#1900).set() now returns a boolean instead of the instance. (#1904)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)@redis/client upgraded to v6 (breaking). (#1954)@keyv/serialize-msgpackr (breaking). (#1958)@keyv/test-suite, expect changes. (#1931)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 cryptoSupports 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 APIWorks 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):
base64([IV (12 bytes) || AuthTag (16 bytes) || Ciphertext])base64([IV (16 bytes) || Ciphertext])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 separatettlto the raw setters.
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; // trueOpt-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)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.
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 them, and several stats/telemetry edge cases were fixed (no STAT_SET on empty set, setRaw telemetry, getManyRaw dead code). (#1922, #1920, #1921, #1919)
Serialization is now optional. Disable it to store raw objects (ideal for the default in-memory Map, where string conversion isn't needed). (#1898)
const keyv = new Keyv({ serialization: false });Pipeline ordering when serialization/compression are configured:
If compression is configured without a serializer, Keyv falls back to JSON.stringify/JSON.parse since compression needs string input.
@keyv/etcd now talks to etcd v3 directly over its HTTP/JSON gateway via a small in-house client — the etcd3 dependency is gone. Requires etcd v3+ and Node.js 20+ (uses global fetch / AbortSignal.timeout). TTL via etcd leases, namespace isolation, async iterator, and setMany/getMany/deleteMany/hasMany are all supported. (#1936, #1893)disconnect() and iterator(); moved to v6 requirements with namespace support; TTL now stored in milliseconds; internal isExpired rename. AWS SDK dependencies upgraded. (#1914, #1894, #1934, #1935, #1948)KeyvCompressionAdapter standard. (#1901)tsdown. (#1926)main-vs-master links and broken logo links in package READMEs. (#1939, #1943)| Package | Change | PR |
|---|---|---|
@redis/client |
→ v6 (breaking) | #1954 |
hookified |
→ v3 (breaking) | #1957 |
hashery (BigMap) |
→ v2 (breaking) | #1956 |
msgpackr (serialize) |
→ v2 (breaking) | #1958 |
bignumber.js (test-suite) |
→ v11 (breaking) | #1955 |
docula (website) |
→ v2 (breaking) | #1947 |
mongodb |
upgraded | #1951 |
mysql2 |
upgraded | #1952 |
pg |
upgraded | #1953 |
| AWS SDK (dynamo) | upgraded | #1948 |
| memcache | upgraded | #1950 |
| TypeScript | → v6 | #1933 |
| GitHub Actions | upgraded (breaking) | #1946 |
v6.0.0-beta.1mono - test: harden service-backed suites against timing flakes (#1960)serialize-msgpackr - chore: upgrade msgpackr to v2 (breaking) (#1958)mono - chore: upgrade hookified to v3 (breaking) (#1957)bigmap - chore: upgrade hashery to v2 (breaking) (#1956)test-suite - chore: upgrade bignumber.js to v11 (breaking) (#1955)redis - chore: upgrade @redis/client to v6 (breaking) (#1954)postgres - chore: upgrade pg (#1953)mysql - chore: upgrade mysql2 (#1952)mongo - chore: upgrade mongodb (#1951)memcache - chore: upgrade memcache (#1950)dynamo - chore: upgrade AWS SDK dependencies (#1948)test-suite - feat: allow storage TTL tests to specify milliseconds or seconds (#1949)website - chore: upgrade docula to v2 (breaking) (#1947)mono - chore: upgrade GitHub Actions (breaking) (#1946)mono - chore: upgrade TypeScript and build tooling (#1945)mono - chore: upgrade code quality dependencies (breaking) (#1944)mono - docs: fix broken keyv logo link in package READMEs (#1943)feat: release management with OIDC and multi versions (#1942)keyv - fix: main branch used instead of master for links (#1939)etcd - feat: replace etcd3 dependency with built-in HTTP/JSON client (#1936)dynamo - fix: renaming internal isExpired (#1935)dynamo - fix: storing ttl in ms now also (#1934)mono - chore: upgrading to TypeScript 6 (#1933)v6.0.0-beta.1keyv - feat (breaking) stats / telemetry overhaul (#1912)keyv - feat: (breaking) memory adapter, bridge adapter, keyv overhaul (#1913)bigmap - feat: optimize BigMap hash function and hot path performance (#1915)dynamo - feat: add disconnect and iterator methods to KeyvDynamo (#1914)keyv - fix: handling has and hasMany better (#1916)keyv - fix: adding in decode expiring to has (#1917)keyv - feat: adding hooks for setMany and deleteMany (#1918)keyv - fix: dead code on getManyRaw (#1919)keyv - fix: on set with no result do not send telemetry STAT_SET (#1920)keyv - fix: telemetry issue on setRaw (#1921)keyv - fix: having encode / decode propagate errors (#1922)keyv - feat: (breaking) by default keyv no longer checks expires (#1923)keyv - feat: adding in hooks for clear and disconnect (#1924)keyv - fix: minor bug fixes on memory, ttl, etc (#1925)mono - feat: moving to tsdown for build (#1926)encryption-node - feat: add Node.js encryption adapter for Keyv (#1927)encrypt-web - feat: adding new web crypto module (#1928)keyv - feat: (breaking) removing StoredData and StoredDataRaw types (#1929)keyv - feat: enhancing capabilities (#1930)test-suite - feat (breaking) overhaul based on v6 changes (#1931)v6.0.0-alpha.4keyv - feat: (breaking) moving to Hookified (#1900)compression - feat: moving to KeyvCompressionAdapter standard (#1901)keyv - feat: (breaking) api changes and iterator simplification (#1902)keyv - feat: moving storage setMany to use KeyvEntry (#1903)keyv - feat: (breaking) moving to boolean return on set (Note truncated.
keyv - feat (breaking) stats / telemetry overhaul by @jaredwray in #1912
Full Changelog: v6.0.0-alpha.4...v6.0.0-beta.1
sqlite - feat: moving to namespace and modern adapter methods by @jaredwray in #1884
Full Changelog: v6.0.0-alpha.2...v6.0.0-alpha.3
valkey - feat: moving options to properties by @jaredwray in #1876
Full Changelog: 6.0.0-alpha.1...v6.0.0-alpha.2
redis - feat: exporting RedisSentinelOptions by @jaredwray in #1823
Full Changelog: 2026-01-20...6.0.0-alpha.1
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →