Skip to content

DynamoDB Store

@http-client-toolkit/store-dynamodb provides distributed stores backed by Amazon DynamoDB. Designed for serverless and multi-instance production deployments where state must be shared across processes.

Terminal window
npm install @http-client-toolkit/store-dynamodb @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb

The AWS SDK packages are peer dependencies — you likely already have them in a serverless project.

All stores share a single DynamoDB table. The library does not create tables at runtime. You must provision the table in infrastructure first.

If the table is missing, store operations throw a clear error:

DynamoDB table “<table-name>” was not found. Create the table using your infrastructure before using DynamoDB stores.

You can reference the required schema from code:

import {
TABLE_SCHEMA,
DEFAULT_TABLE_NAME,
} from '@http-client-toolkit/store-dynamodb';

Enable DynamoDB native TTL on the ttl attribute for automatic item expiration.

import { StackContext } from 'sst/constructs';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
export function Storage({ stack }: StackContext) {
const table = new dynamodb.Table(stack, 'HttpClientToolkitTable', {
tableName: 'http-client-toolkit',
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
partitionKey: { name: 'pk', type: dynamodb.AttributeType.STRING },
sortKey: { name: 'sk', type: dynamodb.AttributeType.STRING },
timeToLiveAttribute: 'ttl',
});
table.addGlobalSecondaryIndex({
indexName: 'gsi1',
partitionKey: { name: 'gsi1pk', type: dynamodb.AttributeType.STRING },
sortKey: { name: 'gsi1sk', type: dynamodb.AttributeType.STRING },
projectionType: dynamodb.ProjectionType.ALL,
});
}

All DynamoDB stores accept a DynamoDBDocumentClient, a plain DynamoDBClient (auto-wrapped), or no client (created internally with optional region):

import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import {
DynamoDBCacheStore,
DynamoDBDedupeStore,
DynamoDBRateLimitStore,
} from '@http-client-toolkit/store-dynamodb';
const dynamoClient = new DynamoDBClient({ region: 'us-east-1' });
const cache = new DynamoDBCacheStore({ client: dynamoClient });
const dedupe = new DynamoDBDedupeStore({ client: dynamoClient });
const rateLimit = new DynamoDBRateLimitStore({ client: dynamoClient });
new DynamoDBCacheStore({
client: dynamoClient,
tableName: 'http-client-toolkit', // Default
maxEntrySizeBytes: 390 * 1024, // Default: 390 KB
});
OptionTypeDefaultDescription
clientDynamoDBClient | DynamoDBDocumentClientAuto-createdDynamoDB client
tableNamestring'http-client-toolkit'Table name
maxEntrySizeBytesnumber399_360Max entry size (DynamoDB 400 KB limit minus overhead)
new DynamoDBDedupeStore({
client: dynamoClient,
jobTimeoutMs: 300_000, // Default: 5 minutes
pollIntervalMs: 500, // Default: 500ms
});
OptionTypeDefaultDescription
clientDynamoDBClient | DynamoDBDocumentClientAuto-createdDynamoDB client
jobTimeoutMsnumber300_000Timeout for in-flight jobs
pollIntervalMsnumber500Poll interval (higher than SQLite to reduce API calls)
new DynamoDBRateLimitStore({
client: dynamoClient,
defaultConfig: { limit: 60, windowMs: 60_000 },
resourceConfigs: new Map([
['slow-api', { limit: 10, windowMs: 60_000 }],
]),
});
OptionTypeDefaultDescription
clientDynamoDBClient | DynamoDBDocumentClientAuto-createdDynamoDB client
defaultConfig{ limit, windowMs }RequiredDefault rate limit
resourceConfigsMap<string, { limit, windowMs }>undefinedPer-resource overrides
new DynamoDBAdaptiveRateLimitStore({
client: dynamoClient,
defaultConfig: { limit: 200, windowMs: 3_600_000 },
adaptiveConfig: {
highActivityThreshold: 10,
moderateActivityThreshold: 3,
},
});

See the Memory store adaptive config for details on the adaptive strategies and configuration options.

  • No cleanup intervals — DynamoDB native TTL handles automatic item expiration. No background timers needed.
  • TTL lag — DynamoDB TTL deletion can be delayed up to 48 hours. Stores check ttl in get() to filter expired items immediately.
  • Single-table design — All store types share one table, separated by key prefixes (CACHE#, DEDUPE#, RATELIMIT#).
  • clear() is expensive — Uses Scan + BatchWriteItem. DynamoDB has no truncate operation.
  • GSI for priority queries — The adaptive rate limit store uses the gsi1 GSI to efficiently query requests by priority.