Skip to content

SQLite Store

@http-client-toolkit/store-sqlite provides persistent stores backed by SQLite via better-sqlite3 and Drizzle ORM. Data survives process restarts.

Terminal window
npm install @http-client-toolkit/store-sqlite

All SQLite stores accept either a file path or an existing better-sqlite3 Database instance.

Passing a shared instance lets multiple stores operate on the same database file:

import Database from 'better-sqlite3';
import {
SQLiteCacheStore,
SQLiteDedupeStore,
SQLiteRateLimitStore,
} from '@http-client-toolkit/store-sqlite';
const db = new Database('./app.db');
const cache = new SQLiteCacheStore({ database: db });
const dedupe = new SQLiteDedupeStore({ database: db });
const rateLimit = new SQLiteRateLimitStore({ database: db });

When a file path is passed, the store manages its own connection and closes it when close() is called:

const cache = new SQLiteCacheStore({ database: './cache.db' });
// ... use the cache ...
cache.close(); // Closes the managed connection

By default, stores use ':memory:' (non-persistent).

new SQLiteCacheStore({
database: './cache.db', // Default: ':memory:'
cleanupIntervalMs: 60_000, // Set to 0 to disable
maxEntrySizeBytes: 5_242_880, // Default: 5 MiB
});
OptionTypeDefaultDescription
databasestring | Database':memory:'File path or Database instance
cleanupIntervalMsnumber60_000Expired entry cleanup interval. 0 to disable.
maxEntrySizeBytesnumber5_242_880Maximum entry size (5 MiB)
new SQLiteDedupeStore({
database: './dedupe.db',
jobTimeoutMs: 300_000,
cleanupIntervalMs: 60_000,
pollIntervalMs: 100,
});
OptionTypeDefaultDescription
databasestring | Database':memory:'File path or Database instance
jobTimeoutMsnumber300_000Timeout for in-flight jobs
cleanupIntervalMsnumber60_000Stale job cleanup interval
pollIntervalMsnumber100Poll interval for cross-instance waiters

The SQLite dedupe store supports cross-instance deduplication — multiple Node.js processes sharing the same database file can deduplicate against each other via polling.

Pending waiters are settled when the store is closed, preventing hanging promises during shutdown.

new SQLiteRateLimitStore({
database: './ratelimit.db',
defaultConfig: { limit: 60, windowMs: 60_000 },
resourceConfigs: new Map([
['slow-api', { limit: 10, windowMs: 60_000 }],
]),
});
OptionTypeDefaultDescription
databasestring | Database':memory:'File path or Database instance
defaultConfig{ limit, windowMs }RequiredDefault rate limit
resourceConfigsMap<string, { limit, windowMs }>undefinedPer-resource overrides

Priority-aware rate limiter with the same adaptive strategies as the in-memory variant, backed by SQLite for persistence.

new SqliteAdaptiveRateLimitStore({
database: './ratelimit.db',
defaultConfig: { limit: 200, windowMs: 3_600_000 },
resourceConfigs: new Map([
['search', { limit: 50, windowMs: 60_000 }],
]),
adaptiveConfig: {
highActivityThreshold: 10,
moderateActivityThreshold: 3,
monitoringWindowMs: 900_000,
maxUserScaling: 2.0,
},
});

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