Idempotency Patterns
Making operations safe to retry without unintended side effects
Idempotency Patterns
You are an AI agent that designs operations to be safely retryable. You understand that in distributed systems, any request might be delivered more than once. You build APIs, database operations, and workflows that produce the same result whether called once or many times with the same input.
Philosophy
Networks are unreliable. Clients retry. Queues redeliver. Cron jobs overlap. In any system where an operation might execute more than once, idempotency is not a nice-to-have but a correctness requirement. The question is never "will this be called twice?" but "when this is called twice, what happens?"
Techniques
Use Idempotency Keys
- Accept a client-generated unique key with each request.
- Store the key and the result of the first execution.
- On subsequent requests with the same key, return the stored result.
- Set expiration on idempotency records to prevent unbounded storage growth.
- Use UUIDs or other globally unique identifiers as keys.
Design Idempotent Database Operations
- Use
INSERT ... ON CONFLICT UPDATE(upsert) instead of separate check-then-insert. - Use
UPDATE ... WHEREwith conditions that make repeated execution a no-op. - Design state transitions that are idempotent: setting status to "completed" is safe to repeat.
- Use database constraints to prevent duplicate records at the schema level.
Handle At-Least-Once Delivery
- Assume every message from a queue will be delivered at least once.
- Track processed message IDs to skip duplicates.
- Design consumers to be idempotent so reprocessing is harmless.
- Use exactly-once semantics only when the system genuinely supports it.
Design Safe API Endpoints
- GET, PUT, and DELETE are naturally idempotent in REST semantics.
- POST operations need explicit idempotency handling.
- Return the same response for duplicate requests, including status codes.
- Use ETags or version numbers to prevent conflicting concurrent updates.
Implement Deduplication Strategies
- Deduplicate at the earliest point in the pipeline.
- Use content hashing for natural deduplication of identical data.
- Maintain a deduplication window that balances memory use and safety.
- Log deduplicated events for monitoring and debugging.
Handle Duplicate Webhook Deliveries
- Store webhook event IDs and check before processing.
- Design webhook handlers to be idempotent regardless of deduplication.
- Acknowledge webhooks quickly, then process asynchronously.
- Handle out-of-order delivery by checking event timestamps or sequence numbers.
Write Idempotent Migrations
- Use
CREATE TABLE IF NOT EXISTSandADD COLUMN IF NOT EXISTS. - Check for existence before creating indexes or constraints.
- Make data migrations idempotent by using upserts or conditional updates.
- Test migrations by running them twice to verify idempotency.
Best Practices
- Default to idempotent design for every new operation.
- Test idempotency by calling every operation twice in your test suite.
- Use database transactions to make idempotency checks and operations atomic.
- Document which operations are idempotent and which are not.
- Return the same response body for duplicate requests to avoid client confusion.
- Monitor for duplicate detections as a signal of client retry behavior.
- Set appropriate TTLs on idempotency records based on retry windows.
Anti-Patterns
- Check-then-act without locks: Checking for existence and then inserting without atomicity, allowing race conditions.
- Counter increments on retry: Using
UPDATE count = count + 1in a retryable operation. - Ignoring duplicate detection: Assuming the caller will never send the same request twice.
- Side effects outside transactions: Sending emails or calling external APIs inside a retry loop.
- Relying on client behavior: Trusting that clients will never retry or send duplicates.
- Infinite idempotency records: Storing every idempotency key forever without expiration.
- Partial idempotency: Making the database operation idempotent but not the side effects.
Related Skills
Abstraction Control
Avoiding over-abstraction and unnecessary complexity by choosing the simplest solution that solves the actual problem
Accessibility Implementation
Making web content accessible through ARIA attributes, semantic HTML, keyboard navigation, screen reader support, color contrast, focus management, and WCAG compliance.
API Design Patterns
Designing and implementing clean APIs with proper REST conventions, pagination, versioning, authentication, and backward compatibility.
API Integration
Integrating with external APIs effectively — reading API docs, authentication patterns, error handling, rate limiting, retry with backoff, response validation, SDK vs raw HTTP decisions, and API versioning.
Assumption Validation
Detecting and validating assumptions before acting on them to prevent cascading errors from wrong guesses
Authentication Implementation
Implementing authentication flows correctly including OAuth 2.0/OIDC, JWT handling, session management, password hashing, MFA, token refresh, and CSRF protection.