Skip to main content

Overview

The idempotency middleware ensures that repeated requests with the same idempotency key return the same response, preventing duplicate operations like double charges or duplicate records. Use it when you need:
  • Safe payment processing retries
  • Duplicate request prevention
  • Reliable webhook handling

Installation

Quick Start

Client sends:

Configuration

Options

Examples

Basic Usage

Custom Header

Specific Methods Only

User-Scoped Keys

Custom Store

How It Works

  1. Client sends request with Idempotency-Key header
  2. Middleware checks if key exists in store
  3. If exists: returns cached response with Idempotent-Replayed: true
  4. If not: executes handler, caches response, returns normally
  5. Subsequent requests with same key get cached response

API Reference

Functions

Store Interface

Response Headers

Technical Details

Cache Key Generation

By default, the middleware generates cache keys using SHA-256 hashing of:
  • The idempotency key from the header
  • The HTTP method (POST, PUT, etc.)
  • The request URL path
This ensures that the same idempotency key can be safely reused across different endpoints and methods.

Response Capture

The middleware uses a custom responseCapture wrapper that:
  1. Captures the response status code (defaults to 200 OK)
  2. Clones all response headers
  3. Buffers the response body in memory
  4. Writes everything to both the buffer and the underlying ResponseWriter

Memory Store Implementation

The built-in MemoryStore:
  • Uses sync.RWMutex for thread-safe concurrent access
  • Runs a background cleanup goroutine that removes expired entries every 10 minutes
  • Stores responses with their expiration timestamps
  • Returns nil for expired entries automatically

Request Flow

  1. Method Check: Verifies the HTTP method is in the configured Methods list
  2. Key Extraction: Retrieves the idempotency key from the specified header
  3. Cache Lookup: Checks if a response exists for the generated cache key
  4. Cache Hit: If found and not expired, replays the cached response with Idempotent-Replayed: true header
  5. Cache Miss: Wraps the ResponseWriter, executes the handler, captures the response, and stores it in the cache
  6. Expiration: Responses are stored with a TTL and automatically cleaned up

Best Practices

  • Always use idempotency keys for payment operations
  • Generate unique keys client-side (UUIDs work well)
  • Include user context in key generation for multi-tenant apps
  • Set appropriate TTL based on your use case
  • Use distributed store (Redis) for multi-instance deployments

Testing

Test Coverage

Client Example