Keyv Documentation
repository·main·Indexed 25 days ago
https://github.com/jaredwray/keyvA simple key-value storage library providing a consistent API across multiple backends via storage adapters. It supports caching with TTL and persistent storage. The ecosystem includes various storage adapters (Redis, MongoDB, SQLite, Postgres, MySQL, etc.), compression adapters (Brotli, Gzip, LZ4), and @keyv/bigmap, a scalable Map implementation designed to exceed the native JavaScript Map entry limit.
What's inside Keyv
- Keyv provides best-effort support for the Bun runtime. While Node.js is the primary target, tests are run against Bun to ensure compatibility.
Use BigMap for large-scale key-value storage
mainUse@keyv/bigmapwhen you need to scale past the native JavaScriptMapentry limit (approximately 16.7 million entries).BigMapdistributes keys across multiple internalMapinstances using a hash function. While it has a slight performance overhead compared to a nativeMapfor smaller datasets, it allows for much larger datasets by avoiding the single-map limit.Keyv v5 New Features Overview
mainKeyv v5 includes several significant improvements:
- TypeScript Support: Full native TypeScript support.
- ESM Support: Written in ESM with full support.
- Event Emitter: Emits events for
set,delete,clear, anderrorwithout third-party dependencies. - Built-in Statistics: Tracks
hits,misses,sets,deletes, anderrors. - Hooks: Provides pre and post processing hooks for
set(),get(),getMany(), anddelete().
Understand the Keyv processing pipeline
mainWhen serialization, compression, and/or encryption are configured, Keyv applies them in a specific order:
On set:
serialize→compress(optional) →encrypt(optional) →storeOn get:
store→decrypt(optional) →decompress(optional) →parse→valueCompression and encryption only run if a serializer is configured. If
serialization: falseis used, values are passed to the store as-is.Understand Keyv package versioning (v6+)
mainStarting with v6, Keyv moved to a unified versioning model. Every package in the family—including the corekeyvpackage and all official adapters (e.g.,@keyv/redis,@keyv/postgres)—shares a single version number and is released simultaneously. This ensures that the version number acts as a compatibility statement (e.g.,keyv@6.2.0is guaranteed to work with@keyv/redis@6.2.0).Install and use Keyv
mainKeyv provides a consistent interface for key-value storage across multiple backends. By default, it uses in-memory storage. To use persistent backends, you must install a specific storage adapter (e.g.,
@keyv/redis).import Keyv from 'keyv'; const keyv = new Keyv(); await keyv.set('foo', 'bar'); await keyv.get('foo'); // 'bar'Install Keyv and Redis adapter for NestJS
mainTo use Keyv with Redis in a NestJS project, install the
cacheablepackage and the@keyv/redisadapter:$ npm install cacheable @keyv/redis --saveConfigure TTL and Expiration behavior
mainKeyv computes an absolute expiry (Unix timestamp in milliseconds) and sends it to Redis using the
PXAToption. This ensures immunity to clock skew and network latency.- Redis 6.2+: Uses
PXATfor absolute expiry. - Older versions: Automatically falls back to the relative
PXoption (remaining lifetime in milliseconds).
No manual configuration is required; the adapter detects the Redis version on the first expiring write and caches the result.
- Redis 6.2+: Uses
Integrate @keyv/redis with NestJS
mainTo use
@keyv/redisin a NestJS application, follow these steps:Install dependencies:
npm install @keyv/redis keyv @nestjs/cache-manager cache-manager cacheableCreate a Cache Module using
NestCacheModule.registerAsyncandcreateKeyv.Register the module in your
AppModule.Create a Cache Service that injects
CACHE_MANAGERto provide a typed wrapper forget,set, anddeleteoperations.
import { Module } from '@nestjs/common'; import { CacheModule as NestCacheModule } from '@nestjs/cache-manager'; import { createKeyv } from '@keyv/redis'; @Module({ imports: [ NestCacheModule.registerAsync({ useFactory: () => ({ stores: [createKeyv('redis://localhost:6379')], }), }), ], providers: [], exports: [], }) export class CacheModule {}Use third-party storage adapters
mainAny store that implements the
MapAPI can be used as a Keyv store. Keyv will wrap these adapters in TTL functionality and handle complex types internally.import Keyv from 'keyv'; import myAdapter from 'my-adapter'; const keyv = new Keyv({ store: myAdapter });Enable WAL mode for better performance
mainEnabling Write-Ahead Logging (WAL) mode can significantly improve concurrency and write performance. In WAL mode, readers do not block writers and vice versa.
Note: WAL mode is not supported for in-memory databases (
:memory:). If enabled for an in-memory database, a warning will be logged and the option will be ignored.const store = new KeyvSqlite({ uri: 'sqlite://path/to/database.sqlite', wal: true, });Use Namespaces for Key Isolation
mainNamespaces prefix every key with
namespace:. To ensure isolation, it is recommended to give each namespace its ownKeyvMemcacheinstance.Warning: The
clear()method always flushes the entire Memcached server because Memcached cannot enumerate keys; it is not scoped to a namespace.import Keyv from 'keyv'; import KeyvMemcache from '@keyv/memcache'; const keyv1 = new Keyv({ store: new KeyvMemcache('localhost:11211'), namespace: "namespace1" }); const keyv2 = new Keyv({ store: new KeyvMemcache('localhost:11211'), namespace: "namespace2" }); //set await keyv1.set("foo","bar1", 6000) await keyv2.set("foo","bar2", 6000) //get const obj1 = await keyv1.get("foo"); //will return bar1 const obj2 = await keyv2.get("foo"); //will return bar2