JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 1134
  • Score
    100M100P100Q113311F
  • License MIT

DynamoDB storage adapter for Keyv

Package Exports

  • @keyv/dynamo

Readme

@keyv/dynamo keyv

DynamoDB storage adapter for Keyv

build codecov GitHub license npm npm

Features

  • Built on @aws-sdk/client-dynamodb and @aws-sdk/lib-dynamodb with full TypeScript support
  • TTL support via DynamoDB TTL indexes (6-hour default when no TTL is specified)
  • Namespace support for key isolation across multiple Keyv instances
  • Automatic table creation with PAY_PER_REQUEST billing mode
  • setMany, getMany, deleteMany, and hasMany batch operations
  • Async iterator support with namespace-aware filtering
  • createKeyv helper for quick setup

Note: DynamoDB doesn't guarantee data will be deleted immediately upon expiration. See the DynamoDB TTL documentation for details.

Table of Contents

Install

npm install --save keyv @keyv/dynamo

Quick Start with createKeyv

import { createKeyv } from '@keyv/dynamo';

const keyv = createKeyv({ endpoint: 'http://localhost:8000' });

// set a value
await keyv.set('foo', 'bar');

// get a value
const value = await keyv.get('foo');

// set with TTL (milliseconds)
await keyv.set('foo', 'bar', 6000);

// delete a value
await keyv.delete('foo');

You can also pass options:

import { createKeyv } from '@keyv/dynamo';

const keyv = createKeyv({
  endpoint: 'http://localhost:8000',
  tableName: 'cacheTable',
  namespace: 'my-app',
});

Usage

import Keyv from 'keyv';
import KeyvDynamo from '@keyv/dynamo';

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
const keyv = new Keyv(store, { useKeyPrefix: false });

// set a value
await keyv.set('foo', 'bar');

// set a value with TTL (in milliseconds)
await keyv.set('foo', 'bar', 6000);

// get a value
const value = await keyv.get('foo');

// delete a value
await keyv.delete('foo');

// clear all values
await keyv.clear();

Usage with Namespaces

import Keyv from 'keyv';
import KeyvDynamo from '@keyv/dynamo';

const store1 = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
store1.namespace = 'namespace1';
const keyv1 = new Keyv(store1, { namespace: 'namespace1', useKeyPrefix: false });

const store2 = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
store2.namespace = 'namespace2';
const keyv2 = new Keyv(store2, { namespace: 'namespace2', useKeyPrefix: false });

// keys are isolated by namespace
await keyv1.set('foo', 'bar1');
await keyv2.set('foo', 'bar2');

const value1 = await keyv1.get('foo'); // 'bar1'
const value2 = await keyv2.get('foo'); // 'bar2'

Usage with NestJS

Since DynamoDB has a 400KB limit per item, compressing data can help in some cases.

With a payload less than or equal to 400KB

import { Keyv } from 'keyv'
import { KeyvDynamo } from '@keyv/dynamo'
import { CacheModule } from '@nestjs/cache-manager'
import { Module } from '@nestjs/common'

@Module({
  imports: [
    CacheModule.registerAsync({
      isGlobal: true,
      useFactory: async () => {
        return {
          stores: [
            new Keyv({
              store: new KeyvDynamo({
                tableName: 'TableName',
              }),
            }),
          ],
        }
      },
    }),
  ],
})
export class InfrastructureModule {}

With a payload greater than 400KB

import { Keyv } from 'keyv'
import KeyvBrotli from '@keyv/compress-brotli'
import { KeyvDynamo } from '@keyv/dynamo'
import { CacheModule } from '@nestjs/cache-manager'
import { Module } from '@nestjs/common'

@Module({
  imports: [
    CacheModule.registerAsync({
      isGlobal: true,
      useFactory: async () => {
        return {
          stores: [
            new Keyv({
              store: new KeyvDynamo({
                tableName: 'TableName',
              }),
              compression: new KeyvBrotli(),
            }),
          ],
        }
      },
    }),
  ],
})
export class InfrastructureModule {}

Options

Options extend DynamoDBClientConfig so all AWS SDK options (endpoint, region, credentials, etc.) are supported.

Option Type Default Description
tableName string 'keyv' The DynamoDB table name. Created automatically if it doesn't exist.
namespace string undefined Key prefix for namespace isolation
endpoint string The DynamoDB endpoint URL (e.g., 'http://localhost:8000' for local development)
uri string Alias for endpoint (for consistency with other Keyv adapters). endpoint takes precedence when both are set.
region string The AWS region (e.g., 'us-east-1')
import KeyvDynamo from '@keyv/dynamo';

// Using an endpoint string
const store = new KeyvDynamo('http://localhost:8000');

// Using an options object
const store2 = new KeyvDynamo({ endpoint: 'http://localhost:8000', tableName: 'cacheTable' });

Properties

.client

The underlying DynamoDBDocument client instance. Can be used to access the DynamoDB client directly.

Type Default
DynamoDBDocument Created from the options

.namespace

Key prefix for namespace isolation. When set, all keys are prefixed with namespace:.

Type Default
string | undefined undefined

.keyPrefixSeparator

The separator between the namespace and key.

Type Default
string ':'

.sixHoursInMilliseconds

The default TTL fallback in milliseconds. Used when no TTL is specified in a set() call.

Type Default
number 21600000 (6 hours)

.tableName

The DynamoDB table name in use. Read-only.

Type Default
string 'keyv'

.endpoint

The configured DynamoDB endpoint URL, if one was provided. Read-only.

Type Default
string | undefined undefined

Methods

constructor(options?)

Creates a new KeyvDynamo instance. Automatically creates the DynamoDB table if it doesn't exist.

  • options — A KeyvDynamoOptions object or an endpoint string. Defaults to { tableName: 'keyv' }.
import KeyvDynamo from '@keyv/dynamo';

// Using an endpoint string
const store = new KeyvDynamo('http://localhost:8000');

// Using an options object
const store2 = new KeyvDynamo({ endpoint: 'http://localhost:8000', tableName: 'cacheTable' });

.get(key)

Retrieves a value from DynamoDB. Returns the stored value or undefined if the key does not exist.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
await store.set('foo', 'bar');
const result = await store.get('foo'); // 'bar'

.getMany(keys)

Retrieves multiple values from DynamoDB. Returns an array of stored data corresponding to each key.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
await store.set('key1', 'value1');
await store.set('key2', 'value2');
const results = await store.getMany(['key1', 'key2']);

.set(key, value, ttl?)

Stores a value in DynamoDB. Uses a 6-hour default TTL if no TTL is specified. TTL is in milliseconds.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
await store.set('foo', 'bar');

// with TTL (milliseconds)
await store.set('foo', 'bar', 60000);

.setMany(entries)

Stores multiple values in DynamoDB using BatchWriteItem in chunks of 25. Each entry is a KeyvEntry<Value> object ({ key: string, value: Value, ttl?: number }), where Value is inferred from the entries provided. Returns a boolean[] with per-entry success tracking — any items reported as UnprocessedItems by DynamoDB are marked as false.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
const results = await store.setMany([
  { key: 'key1', value: 'value1' },
  { key: 'key2', value: 'value2', ttl: 60000 },
]); // [true, true]

.delete(key)

Deletes a key from DynamoDB. Returns true if the key was deleted, false otherwise.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
await store.set('foo', 'bar');
const deleted = await store.delete('foo'); // true

.deleteMany(keys)

Deletes multiple keys from DynamoDB. Returns a boolean[] indicating whether each key was deleted.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
await store.set('key1', 'value1');
await store.set('key2', 'value2');
const results = await store.deleteMany(['key1', 'key2']); // [true, true]

.clear()

Clears data from DynamoDB. If a namespace is set, only keys with the namespace prefix are deleted. Otherwise, all keys are deleted.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
await store.clear();

.has(key)

Checks whether a key exists in DynamoDB.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
await store.set('foo', 'bar');
const exists = await store.has('foo'); // true
const missing = await store.has('baz'); // false

.hasMany(keys)

Checks whether multiple keys exist in DynamoDB. Returns an array of booleans corresponding to each key.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
await store.set('key1', 'value1');
await store.set('key2', 'value2');
const results = await store.hasMany(['key1', 'key2', 'key3']); // [true, true, false]

.iterator()

Returns an async iterator over all [key, value] pairs in the store. If a namespace is set, only keys with that namespace are yielded and the namespace prefix is removed from the returned keys. The namespace does not need to be passed in — it uses the namespace configured on the adapter. Expired entries are skipped and deleted.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
await store.set('key1', 'value1');
await store.set('key2', 'value2');

for await (const [key, value] of store.iterator()) {
  console.log(key, value);
}

.disconnect()

Disconnects from the DynamoDB client. This is a no-op for DynamoDB since it communicates over HTTP requests and does not maintain a persistent connection.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
await store.disconnect();

.formatKey(key)

Formats a key by prepending the namespace if one is set. If the key already starts with the namespace prefix, it is returned as-is to avoid double-prefixing.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
store.formatKey('foo'); // 'foo'

store.namespace = 'myapp';
store.formatKey('foo'); // 'myapp:foo'
store.formatKey('myapp:foo'); // 'myapp:foo' (no double-prefix)

.createKeyPrefix(key, namespace?)

Creates a prefixed key by prepending the namespace and separator. Returns the key as-is if no namespace is provided.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
store.createKeyPrefix('key', 'ns'); // 'ns:key'
store.createKeyPrefix('key'); // 'key'

.removeKeyPrefix(key, namespace?)

Removes the namespace prefix from a key. Returns the key as-is if no namespace is provided.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
store.removeKeyPrefix('ns:key', 'ns'); // 'key'
store.removeKeyPrefix('key'); // 'key'

.ensureTable(tableName)

Ensures the DynamoDB table exists and is active. If the table is in CREATING status, waits for it to become active. If it doesn't exist, creates it.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
await store.ensureTable('my-table');

.createTable(tableName)

Creates a new DynamoDB table with TTL support enabled on the expiresAt attribute. Uses PAY_PER_REQUEST billing mode.

const store = new KeyvDynamo({ endpoint: 'http://localhost:8000' });
await store.createTable('my-table');

License

MIT © Jared Wray