@keyv/dynamo
Table of Contents
DynamoDB storage adapter for Keyv
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_REQUESTbilling mode setMany,getMany,deleteMany, andhasManybatch operationscreateKeyvhelper 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
- Quick Start with createKeyv
- Usage
- Usage with Namespaces
- Usage with NestJS
- Options
- Properties
- Methods
- License
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) |
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) |
Methods
constructor(options?)
Creates a new KeyvDynamo instance. Automatically creates the DynamoDB table if it doesn't exist.
options— AKeyvDynamoOptionsobject 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 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]
.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');