2.5 KiB
storage-adapter
(no submodules)
Purpose
Defines the RateLimitStorage interface — the pluggable persistence contract that decouples rate-limit state from any specific backend. All algorithm implementations and the RateLimiterInstance orchestrator depend only on this interface, making it possible to swap in Redis, SurrealDB, Postgres, or any key-value store without modifying core logic.
The interface is intentionally minimal: four async methods covering read, write, delete, and clear. The ttl parameter on set is advisory: conformant backends SHOULD honour it, but the algorithms are defensive against stale state.
Features
get(key)— returnsRateLimitState | null(null means absent or expired)set(key, state, ttl)— persist with advisory TTL in millisecondsdelete(key)— idempotent removalclear()— full eviction (tests and admin reset)- Zero runtime code — pure interface definition
Usage: Basic Example
import type { RateLimitStorage } from "@suaveplan/rate-limiter";
class RedisStorage implements RateLimitStorage {
async get(key: string) { /* ... */ return null; }
async set(key: string, state, ttl: number) { /* ... */ }
async delete(key: string) { /* ... */ }
async clear() { /* ... */ }
}
Usage: Advanced Example
import { createRateLimiter } from "@suaveplan/rate-limiter";
import type { RateLimitStorage } from "@suaveplan/rate-limiter";
// Provide a Redis-backed storage for distributed rate limiting:
const storage: RateLimitStorage = new RedisStorage(redisClient);
const limiter = createRateLimiter({
defaultConfig: { limit: 1000, window: 60_000 },
storage,
});
const result = await limiter.check({ key: "tenant:acme:user:7" });
API Reference
RateLimitStorage
Interface with four methods:
| Method | Signature | Description |
|---|---|---|
get |
(key: string) => Promise<RateLimitState | null> |
Read state or null |
set |
(key: string, state: RateLimitState, ttl: number) => Promise<void> |
Write with TTL |
delete |
(key: string) => Promise<void> |
Remove key |
clear |
() => Promise<void> |
Remove all entries |
Implementation Notes
The ttl passed to set is derived by the caller from the remaining window duration. Backends that do not support native TTL (e.g. in-process Maps) should store the expiry timestamp alongside the state and filter it in get. The built-in MemoryStorage follows this pattern.