Keyv Documentation

repository·main·Indexed 25 days ago

https://github.com/jaredwray/keyv

A 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.

Tokens
72.8K
Snippets
239
Records
430
Agent score
84%

What's inside Keyv

  1. Use BigMap for large-scale key-value storage

    main
    Use @keyv/bigmap when you need to scale past the native JavaScript Map entry limit (approximately 16.7 million entries). BigMap distributes keys across multiple internal Map instances using a hash function. While it has a slight performance overhead compared to a native Map for smaller datasets, it allows for much larger datasets by avoiding the single-map limit.
  2. Keyv v5 New Features Overview

    main

    Keyv 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, and error without third-party dependencies.
    • Built-in Statistics: Tracks hits, misses, sets, deletes, and errors.
    • Hooks: Provides pre and post processing hooks for set(), get(), getMany(), and delete().
  3. Understand the Keyv processing pipeline

    main

    When serialization, compression, and/or encryption are configured, Keyv applies them in a specific order:

    On set: serializecompress (optional) → encrypt (optional) → store

    On get: storedecrypt (optional) → decompress (optional) → parsevalue

    Compression and encryption only run if a serializer is configured. If serialization: false is used, values are passed to the store as-is.

  4. Understand Keyv package versioning (v6+)

    main
    Starting with v6, Keyv moved to a unified versioning model. Every package in the family—including the core keyv package 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.0 is guaranteed to work with @keyv/redis@6.2.0).
  5. Install and use Keyv

    main

    Keyv 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'
  6. Configure TTL and Expiration behavior

    main

    Keyv computes an absolute expiry (Unix timestamp in milliseconds) and sends it to Redis using the PXAT option. This ensures immunity to clock skew and network latency.

    • Redis 6.2+: Uses PXAT for absolute expiry.
    • Older versions: Automatically falls back to the relative PX option (remaining lifetime in milliseconds).

    No manual configuration is required; the adapter detects the Redis version on the first expiring write and caches the result.

  7. Integrate @keyv/redis with NestJS

    main

    To use @keyv/redis in a NestJS application, follow these steps:

    1. Install dependencies: npm install @keyv/redis keyv @nestjs/cache-manager cache-manager cacheable

    2. Create a Cache Module using NestCacheModule.registerAsync and createKeyv.

    3. Register the module in your AppModule.

    4. Create a Cache Service that injects CACHE_MANAGER to provide a typed wrapper for get, set, and delete operations.

    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 {}
  8. Use third-party storage adapters

    main

    Any store that implements the Map API 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 });
  9. Enable WAL mode for better performance

    main

    Enabling 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,
    });
  10. Use Namespaces for Key Isolation

    main

    Namespaces prefix every key with namespace:. To ensure isolation, it is recommended to give each namespace its own KeyvMemcache instance.

    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