1. Examples
  2. Idempotency Keys

Idempotency Keys

Prevent duplicate API requests and ensure safe retries for payments and critical operations.

Deploy to Zuplo
Deploy to Zuplo

Prerequisite: You need a Zuplo account to run this example. Sign up for free

This example demonstrates how to implement idempotency key handling in Zuplo using custom policies. Idempotency keys ensure that duplicate API requests (caused by retries or network issues) don't result in duplicate operations like double charges or duplicate resource creation.

Prerequisites

  • A Zuplo account. You can sign up for free.

Working with this Example

Locally

Working locally is the best way to explore and understand the code for this example. You can get a local version by using the Zuplo CLI:

Terminalbash
npx create-zuplo-api@latest --example idempotency-keys

Deploy this example to Zuplo

It is also possible to deploy this example directly to your Zuplo account and work with it via the Zuplo Portal. You can do this by clicking the Deploy to Zuplo button anywhere on this page.

What is Idempotency?

Idempotency means that making the same request multiple times produces the same result as making it once. This prevents issues like double charges, duplicate orders, or inconsistent data caused by network retries, timeouts, or users clicking submit twice.

This is critical for operations like:

  • Payment processing
  • Order creation
  • Resource provisioning
  • Any operation where duplicates cause problems

Clients include an Idempotency-Key header with a unique value (typically a UUID). If the same key is sent again, the server returns the cached response instead of processing the request again.

How This Example Works

This example uses two custom Zuplo policies that work together:

Inbound Policy (idempotency-inbound)

  1. Extracts the Idempotency-Key header from the request
  2. Checks Zuplo's ZoneCache for a cached response
  3. If found: returns the cached response immediately with X-Idempotent-Replay: true header
  4. If not found: passes the key to the outbound policy and continues processing

Outbound Policy (idempotency-outbound)

  1. Checks if an idempotency key was provided in the original request
  2. For successful responses (2xx), caches the response body and status code
  3. Uses fire-and-forget caching to avoid adding latency

Project Structure

text
├── config/
│   ├── policies.json      # Policy configuration
│   └── routes.oas.json    # Route definitions with policies applied
└── modules/
    ├── idempotency-inbound.ts   # Inbound policy (cache lookup)
    └── idempotency-outbound.ts  # Outbound policy (cache storage)

Configuration

The inbound policy accepts the following options in policies.json:

OptionTypeDefaultDescription
ttlSecondsnumber86400How long to cache responses (in seconds)

Testing with curl

First request (processed normally):

Terminalbash
curl -X POST http://localhost:9000/payments \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: payment-abc-123" \
  -d '{"amount": 100, "currency": "USD"}' \
  -i

Second request with same key (returns cached response):

Terminalbash
curl -X POST http://localhost:9000/payments \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: payment-abc-123" \
  -d '{"amount": 100, "currency": "USD"}' \
  -i

The second request returns the cached response with the X-Idempotent-Replay: true header.

Request without idempotency key (no caching):

Terminalbash
curl -X POST http://localhost:9000/payments \
  -H "Content-Type: application/json" \
  -d '{"amount": 100, "currency": "USD"}'

Note: Replace localhost:9000 with your Zuplo deployment URL (e.g., your-api.zuplo.dev) when testing a deployed project.

Alternative Storage Options

This example uses Zuplo's ZoneCache for simplicity, but you may want external storage for longer retention, global consistency, or durability requirements.

Alternatives include:

  • Upstash Redis: Serverless Redis with a REST API
  • DynamoDB: AWS key-value store with TTL support
  • Neon / PlanetScale: Serverless PostgreSQL/MySQL

When to Use What

StorageBest for
ZoneCacheSimple use cases, short TTLs, getting started quickly
Upstash RedisLow-latency global access, moderate TTLs, serverless environments
DynamoDBAWS environments, long retention, high durability requirements
PostgreSQL/MySQLExisting database infrastructure, complex queries, audit requirements

Extending This Example

This is a minimal implementation. For production use, consider adding:

  • Request fingerprinting: Hash the request body to detect mismatched payloads with the same key
  • User scoping: Prefix cache keys with request.user.sub to isolate keys per user
  • Concurrent request handling: Add a "processing" marker to handle race conditions
  • Selective caching: Only require idempotency keys for specific HTTP methods (POST, PUT, PATCH)

Learn More

  • Implementing Idempotency Keys in REST APIs
  • Custom Code Inbound Policy
  • Custom Code Outbound Policy
  • ZoneCache Documentation
  • Local Development

Quick Links

View on GitHubDocumentation

Run Locally

Clone and run this example:

npx create-zuplo-api --example idempotency-keys

On This Page

Related Examples

Explore more examples in this category

Semantic Caching

Caching

Reduce AI API costs by caching responses for semantically similar queries.

View Example

Custom Rate Limiting

Programmability

Customize the error response users see when they hit your API rate limits.

View Example

Custom Modules

Programmability

Use npm packages and third-party libraries in your Zuplo handlers and policies.

View Example

Dynamic Rate Limits

Programmability

Set different rate limits based on user subscription tier or API key metadata.

View Example
Check all of our Examples

Scale your APIs with
confidence.

Start for free or book a demo with our team.
Book a demoStart for Free
SOC 2 TYPE 2High Performer Spring 2025Momentum Leader Spring 2025Best Estimated ROI Spring 2025Easiest To Use Spring 2025Fastest Implementation Spring 2025

Get Updates From Zuplo

Zuplo logo
© 2026 zuplo. All rights reserved.
Products & Features
API ManagementAI GatewayMCP ServersMCP GatewayDeveloper PortalRate LimitingOpenAPI NativeGitOpsProgrammableAPI Key ManagementMulti-cloudAPI GovernanceMonetizationSelf-Serve DevX
Developers
DocumentationBlogLearning CenterCommunityChangelogIntegrations
Product
PricingSupportSign InCustomer Stories
Company
About UsMedia KitCareersStatusTrust & Compliance
Privacy PolicySecurity PoliciesTerms of ServiceTrust & Compliance
Docs
Pricing
Sign Up
Login
ContactBook a demoFAQ
Zuplo logo
DocsPricingSign Up
Login