--- name: idempotency-handling description: > Implement idempotency keys and handling to ensure operations can be safely retried without duplicate effects. Use when building payment systems, APIs with retries, or distributed transactions. --- # Idempotency Handling ## Table of Contents - [Overview](#overview) - [When to Use](#when-to-use) - [Quick Start](#quick-start) - [Reference Guides](#reference-guides) - [Best Practices](#best-practices) ## Overview Implement idempotency to ensure operations produce the same result regardless of how many times they're executed. ## When to Use - Payment processing - API endpoints with retries - Webhooks and callbacks - Message queue consumers - Distributed transactions - Bank transfers - Order creation - Email sending - Resource creation ## Quick Start Minimal working example: ```typescript import express from "express"; import Redis from "ioredis"; import crypto from "crypto"; interface IdempotentRequest { key: string; status: "processing" | "completed" | "failed"; response?: any; error?: string; createdAt: number; completedAt?: number; } class IdempotencyService { private redis: Redis; private ttl = 86400; // 24 hours constructor(redisUrl: string) { this.redis = new Redis(redisUrl); } async getRequest(key: string): Promise { const data = await this.redis.get(`idempotency:${key}`); return data ? JSON.parse(data) : null; } // ... (see reference guides for full implementation) ``` ## Reference Guides Detailed implementations in the `references/` directory: | Guide | Contents | |---|---| | [Express Idempotency Middleware](references/express-idempotency-middleware.md) | Express Idempotency Middleware | | [Database-Based Idempotency](references/database-based-idempotency.md) | Database-Based Idempotency | | [Stripe-Style Idempotency](references/stripe-style-idempotency.md) | Stripe-Style Idempotency | | [Message Queue Idempotency](references/message-queue-idempotency.md) | Message Queue Idempotency | ## Best Practices ### ✅ DO - Require idempotency keys for mutations - Store request and response together - Set appropriate TTL for idempotency records - Validate request body matches stored request - Handle concurrent requests gracefully - Return same response for duplicate requests - Clean up old idempotency records - Use database constraints for atomicity ### ❌ DON'T - Apply idempotency to GET requests - Store idempotency data forever - Skip validation of request body - Use non-unique idempotency keys - Process same request concurrently - Change response for duplicate requests