Starter Templates
Jumpstart your API gateway development process with our pre-built starter templates
Idempotency Keys
Idempotency keys prevent duplicate requests and cache responses.
npx create-zuplo-api --example idempotency-keysIdempotency Keys Example
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:
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)
- Extracts the
Idempotency-Keyheader from the request - Checks Zuplo's
ZoneCachefor a cached response - If found: returns the cached response immediately with
X-Idempotent-Replay: trueheader - If not found: passes the key to the outbound policy and continues processing
Outbound Policy (idempotency-outbound)
- Checks if an idempotency key was provided in the original request
- For successful responses (2xx), caches the response body and status code
- Uses fire-and-forget caching to avoid adding latency
Project Structure
Configuration
The inbound policy accepts the following options in policies.json:
| Option | Type | Default | Description |
|---|---|---|---|
ttlSeconds | number | 86400 | How long to cache responses (in seconds) |
Testing with curl
First request (processed normally):
Second request with same key (returns cached response):
The second request returns the cached response with the X-Idempotent-Replay: true header.
Request without idempotency key (no caching):
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
| Storage | Best for |
|---|---|
| ZoneCache | Simple use cases, short TTLs, getting started quickly |
| Upstash Redis | Low-latency global access, moderate TTLs, serverless environments |
| DynamoDB | AWS environments, long retention, high durability requirements |
| PostgreSQL/MySQL | Existing 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.subto 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
Other Examples
Jumpstart your API gateway development process with our pre-built starter templates