npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@reaatech/idempotency-middleware-adapter-redis

v1.0.0

Published

Redis storage adapter for @reaatech/idempotency-middleware

Readme

@reaatech/idempotency-middleware-adapter-redis

npm version License: MIT CI

Redis storage adapter for @reaatech/idempotency-middleware. Provides distributed idempotency caching and token-guarded locking backed by Redis via ioredis.

Installation

npm install @reaatech/idempotency-middleware-adapter-redis ioredis
# or
pnpm add @reaatech/idempotency-middleware-adapter-redis ioredis

Feature Overview

  • Token-guarded locking — lock acquisition via SET NX with unique tokens, release via Lua script to prevent accidental unlock by other processes
  • Automatic TTL — cache entries use Redis EX for server-side expiry enforcement
  • Corrupted data recovery — automatically deletes unparseable entries and returns null on get
  • Connection lifecycle — dedicated connect() (ping) and disconnect() (quit) methods
  • Implements StorageAdapter — drop-in replacement for MemoryAdapter in any idempotency setup

Quick Start

import { Redis } from 'ioredis';
import { RedisAdapter } from '@reaatech/idempotency-middleware-adapter-redis';
import { IdempotencyMiddleware } from '@reaatech/idempotency-middleware';

const redis = new Redis('redis://localhost:6379');
const storage = new RedisAdapter(redis);
await storage.connect();

const middleware = new IdempotencyMiddleware(storage, { ttl: 3_600_000 });

const result = await middleware.execute(
  'payment-123',
  { method: 'POST', path: '/charge', body: { amount: 100 } },
  async () => ({ id: 1, status: 'charged' }),
);

API Reference

RedisAdapter

import { RedisAdapter } from '@reaatech/idempotency-middleware-adapter-redis';

const adapter = new RedisAdapter(redisClient);

Constructor

| Param | Type | Description | |---|---|---| | client | Redis | A pre-configured ioredis client instance |

Methods

Implements the full StorageAdapter interface:

| Method | Description | |---|---| | connect() | Pings Redis and marks the adapter as connected | | disconnect() | Calls redis.quit() and marks as disconnected | | get(key) | GET key → JSON parse → IdempotencyRecord \| null | | set(key, record) | SET key data EX ttlSeconds | | delete(key) | DEL key | | acquireLock(key, ttl) | SET lock:key token EX ttl NX — returns true on success | | releaseLock(key) | Lua eval — deletes lock only if the token matches | | waitForLock(key, timeout, pollInterval) | Polls EXISTS lock:key until released or timeout |

Locking Design

The Redis adapter uses token-guarded locks to prevent the ABA problem:

  1. Acquire: SET lock:<key> <randomUUID> EX <ttlSeconds> NX — atomically sets the lock key only if it doesn't exist
  2. Release: Lua eval script that checks GET lock:key == token before DEL — prevents a process from releasing another process's lock after TTL expiry + re-acquisition
  3. Wait: polls EXISTS lock:key at pollInterval until the key disappears or timeout is reached

The lock key is stored at lock:<cacheKey> separate from the data key (<cacheKey>), so lock state never interferes with cached responses.

Usage Patterns

Connection Management

import { Redis } from 'ioredis';
import { RedisAdapter } from '@reaatech/idempotency-middleware-adapter-redis';

const redis = new Redis({
  host: process.env.REDIS_HOST ?? 'localhost',
  port: Number(process.env.REDIS_PORT ?? 6379),
  password: process.env.REDIS_PASSWORD,
  maxRetriesPerRequest: 3,
});

const adapter = new RedisAdapter(redis);
await adapter.connect();

// Graceful shutdown
process.on('SIGTERM', async () => {
  await adapter.disconnect();
  process.exit(0);
});

Distributed Workers

The Redis adapter is designed for multi-process deployments. Multiple Node.js instances sharing the same Redis instance coordinate via the token-guarded locks:

// Worker A and Worker B both execute:
const result = await middleware.execute('same-key', ctx, handler);
// Only one handler executes. Both get the same cached result.

TTL and Lock Configuration

const middleware = new IdempotencyMiddleware(storage, {
  ttl: 86_400_000,        // Cache responses for 24 hours
  lockTimeout: 30_000,    // Wait up to 30 seconds for a lock
  lockTtl: 60_000,        // Lock auto-expires after 60 seconds
  lockPollInterval: 200,  // Check every 200ms
});

Related Packages

License

MIT