Documentation Index
Fetch the complete documentation index at: https://mintlify.com/AmeyaBorkar/throttlekit/llms.txt
Use this file to discover all available pages before exploring further.
throttlekit/postgres provides PostgresStore — a distributed Store backed by PostgreSQL. Every
apply runs the limiter’s existing pure JS transform inside a transaction, serialized per key by a
transaction-scoped advisory lock. This makes concurrent applies on one key atomic without
requiring Redis.
PostgresStore
PostgresStore is an async-only store — it does not implement applySync. Use
await limiter.check(key) on all Postgres-backed limiters.
Options
A
pg.Pool (or any compatible object with connect() and query() methods). ThrottleKit never
ends a pool it does not own — close() on the store only stops the background sweep timer.Unquoted table identifier holding the limiter state. Validated against
^[A-Za-z_][A-Za-z0-9_]*$ (optionally schema.table). Default "throttlekit".Storage key namespace, prefixed as
prefix:key.Create the table and its expiry index on first use if they do not already exist. Default
true.
Set false if you manage schema migrations separately.Interval in ms for the background sweep that reclaims expired rows. Default
60_000 (1 minute).
Set 0 to disable the sweep and rely entirely on lazy expiry (expired rows are invisible to reads
but not removed from disk).Time source for expiry decisions. Defaults to the system clock. Inject a
ManualClock to drive
expiry deterministically in tests.Advisory-Lock Transaction Mechanism
Everyapply call runs the following transaction:
SELECT … FOR UPDATE) is deliberate:
FOR UPDATEcannot lock a row that does not yet exist, so two first-touch transactions on a new key could race and produce an incorrect result.- An advisory lock keyed by
hashtextextended(key, 0)serializes all applies for that key whether or not the row exists, and releases automatically atCOMMIT/ROLLBACK. - Hash collisions only cause over-serialization of unrelated keys very rarely — correctness is unaffected.
EVALSHA guarantee.
Schema
WhenautoCreate: true (the default), PostgresStore creates the following schema on first use:
expires_at index powers the background sweep.
Expiry Semantics
Expiry is keyed off the store’sClock (mirrors how Redis uses its server clock). Expired rows are
filtered on every read via the WHERE expires_at > $now clause — they are immediately invisible
without waiting for the sweep. The background sweep (sweepIntervalMs) removes them from disk to
reclaim storage.
Because every built-in strategy is idempotent with respect to stale state (a TAT in the past clamps
to now, a bucket refills, a window resets), a slightly-late expiry can never change a decision.
Peer Dependency
PostgresStore has pg as a peer dependency. Install it separately:
Usage with rateLimit
Client Interface Types
PgPoolLike
The minimal slice of a pg.Pool ThrottleKit uses. A pg.Pool satisfies this structurally.
PgClientLike
A checked-out pool client. Mirrors pg’s PoolClient.