Express Idempotency Middleware

raw JSON →
1.0.2 verified Sat Apr 25 auth: no javascript

Express middleware for idempotent POST requests using Idempotency-Key header (version 1.0.2, stable release, active development). Provides pluggable stores (Memory, Redis, Postgres), in-flight concurrency control with wait or reject strategies, and safe response replay with header whitelist. TypeScript-first, ESM-only, requires Node ≥18 and Express 4 or 5. Differentiators: built-in in-flight handling via wait timeout polling, stable response fingerprinting, and separate replay header whitelist for security-aware caching of location headers without cookies or auth tokens. Designed for payment, order, and webhook idempotency scenarios.

error SyntaxError: Named export 'idempotencyMiddleware' not found. The requested module 'express-idempotency-middleware' is a CommonJS module which may not support all module.exports as named exports.
cause Using CommonJS require() instead of ESM import
fix
Change to ESM import: import { idempotencyMiddleware } from 'express-idempotency-middleware' or use dynamic import()
error TypeError: store.get is not a function
cause Custom store does not implement required store interface (get, set, delete methods)
fix
Ensure custom store implements Store interface with get(key), set(key, value, ttl?), and delete(key) async methods
error Idempotency-Status: conflict (409)
cause Idempotency-Key reused with different request body or method than original
fix
Ensure all retries use exactly the same request body, headers (except whitelist), and method
breaking ESM-only package: require() throws ERR_REQUIRE_ESM
fix Use ESM imports: import { idempotencyMiddleware } from 'express-idempotency-middleware'
gotcha MemoryStore does not persist across server restarts; use Redis or Postgres store in production
fix Implement custom store implementing Store interface or use provided examples for RedisStore/PostgresStore
gotcha Idempotency-Key is case-sensitive and must be a string; omit or empty key with requireKey:false returns 400
fix Always send a valid non-empty Idempotency-Key header, or set requireKey:true to enforce
deprecated Node.js <18 is not supported; engines field specifies >=18.0.0
fix Upgrade Node.js to version 18 or later
npm install express-idempotency-middleware
yarn add express-idempotency-middleware
pnpm add express-idempotency-middleware

Creates an Express app with idempotency middleware on POST /payments, using MemoryStore, wait strategy for in-flight requests, and replay header whitelist.

import express from 'express';
import { idempotencyMiddleware, MemoryStore } from 'express-idempotency-middleware';

const app = express();
app.use(express.json());

const store = new MemoryStore();

app.post(
  '/payments',
  idempotencyMiddleware({
    store,
    ttlMs: 24 * 60 * 60 * 1000,
    inFlight: { strategy: 'wait', waitTimeoutMs: 3000, pollMs: 100 },
    replay: { headerWhitelist: ['location'] }
  }),
  async (req, res) => {
    const orderId = 'ord_' + Math.random().toString(36).slice(2);
    res.setHeader('Location', `/orders/${orderId}`);
    res.status(201).json({ orderId });
  }
);

app.listen(3000);