GitHub traffic snapshot (rolling window reported by GitHub API).
Totals since 2026-02-12: 141 views and 655 clones.
| Date | Views | Clones |
|---|---|---|
| 2026-03-17 | 0 | 13 |
| 2026-03-16 | 0 | 11 |
| 2026-03-15 | 1 | 14 |
| 2026-03-14 | 0 | 16 |
| 2026-03-13 | 0 | 14 |
| 2026-03-12 | 2 | 12 |
| 2026-03-11 | 0 | 15 |
| 2026-03-10 | 0 | 8 |
| 2026-03-09 | 2 | 10 |
| 2026-03-08 | 0 | 10 |
| 2026-03-07 | 0 | 11 |
| 2026-03-06 | 0 | 12 |
| 2026-03-05 | 0 | 13 |
| 2026-03-04 | 17 | 5 |
| 2026-03-03 | 0 | 12 |
| 2026-03-02 | 0 | 13 |
| 2026-03-01 | 0 | 14 |
| 2026-02-28 | 1 | 11 |
| 2026-02-27 | 1 | 14 |
| 2026-02-26 | 0 | 21 |
| 2026-02-25 | 0 | 18 |
| 2026-02-24 | 3 | 11 |
| 2026-02-23 | 0 | 13 |
| 2026-02-22 | 4 | 12 |
| 2026-02-21 | 6 | 13 |
| 2026-02-20 | 0 | 13 |
| 2026-02-19 | 3 | 15 |
| 2026-02-18 | 18 | 35 |
| 2026-02-17 | 5 | 12 |
| 2026-02-16 | 3 | 17 |
| 2026-02-15 | 17 | 34 |
| 2026-02-14 | 20 | 30 |
| 2026-02-13 | 38 | 183 |
| 2026-02-12 | 0 | 0 |
Updated automatically: 2026-03-19T05:03:59.163Z
Local-only idempotency for Node.js/TypeScript.
- Dedup concurrent executions by key (single in-flight promise).
- Return the same result on retries while TTL is valid.
- Optional failed-result memoization (
cacheFailures). - Abort one caller without canceling shared execution.
- Zero infra (in-memory only).
- Webhook duplicates.
- Client retries.
- Double-submit and double-click actions.
- Accidental job reprocessing.
npm install idempotency-kitimport { IdempotencyLocal } from "idempotency-kit";
const idem = new IdempotencyLocal({ ttlMs: 30_000 });
const charge = await idem.run("charge:order-123", async () => {
return { ok: true, chargeId: "ch_1" };
});new IdempotencyLocal(options?)
createIdempotencyLocal(options?)| Method | Return | Description |
|---|---|---|
run(key, fn, options?) |
Promise<T> |
Executes once per key and memoizes result by TTL. |
runWithMeta(key, fn, options?) |
Promise<{ value: T; meta: RunMeta }> |
Same as run, with resolution metadata. |
delete(key) |
boolean |
Deletes one cached result key. |
clear() |
void |
Clears all cached results. |
prune() |
number |
Removes expired entries and returns removed count. |
getStats() |
IdempotencyStats |
Read runtime counters and sizes. |
dispose() |
void |
Disposes internal cache resources. |
size |
number |
Current result-cache size. |
| Option | Type | Default | Description |
|---|---|---|---|
ttlMs |
number |
30000 |
Success TTL in milliseconds. |
cacheFailures |
boolean |
false |
Cache failed results for dedup/retry behavior. |
failureTtlMs |
number |
ttlMs |
TTL for cached failures. |
maxSize |
number |
undefined |
Max result entries (LRU evicts old entries). |
cleanupIntervalMs |
number \| false |
false |
Periodic cleanup interval. |
keyPrefix |
string |
"" |
Prefix applied as prefix:key. |
| Option | Type | Description |
|---|---|---|
ttlMs |
number |
Override success TTL for this call. |
cacheFailures |
boolean |
Override failure caching behavior for this call. |
failureTtlMs |
number |
Override failure TTL for this call. |
signal |
AbortSignal |
Cancel only this caller wait. |
hit_completedhit_failedinflight_hitmiss_executedmiss_executed_failed
run(key, fn) rules:
- If completed result is valid, returns it (
hit_completed). - If failed result is valid and
cacheFailures=true, throws same error (hit_failed). - If key is in-flight, waits on the same promise (
inflight_hit). - Otherwise executes
fn:- success: caches completed result (
miss_executed) - error: caches failed result only if enabled (
miss_executed_failed)
- success: caches completed result (
Key normalization:
const finalKey = keyPrefix ? `${keyPrefix}:${key}` : key;import { AbortError, IdempotencyLocal, isAbortError } from "idempotency-kit";
const idem = new IdempotencyLocal();
const controller = new AbortController();
const promise = idem.run("job:1", doWork, { signal: controller.signal });
controller.abort();
try {
await promise;
} catch (error) {
if (isAbortError(error)) {
// this caller stopped waiting
}
}Aborting one caller does not cancel the shared loader for other callers.
AbortError: thrown when caller signal is aborted.isAbortError(error): type-safe helper.
getStats() returns:
runshitsCompletedhitsFailedinflightHitsmissesExecutedmissesExecutedFailedabortedWaitssizeinFlight
Run:
npm run benchIncluded scenarios:
- Miss path (
runwith unique key). - Hit path (
runwith warm key). - 100 concurrent calls same key (dedup).
- LRU pressure under
maxSize. - Expiration cleanup with
prune().
See BENCHMARK.md for details.
Date: February 13, 2026
Environment: Windows + Node v22.19.0 + Vitest 3.2.4
| Scenario | Throughput (hz) |
|---|---|
run miss (new key each call) |
672,647.73 |
run hit (same key) |
707,083.15 |
inflight dedup (100 concurrent same key) |
120.37 |
lru pressure (maxSize=1_000, 2_000 inserts) |
544.62 |
prune expired (5_000 keys) |
40.83 |
npm run typecheck
npm test
npm run build- Cache is per process; no cross-instance guarantees.
undefinedreturn values are cached normally.- Default
cacheFailuresisfalse.
MIT (LICENSE)