Skip to content
Back to skills

Idempotent Endpoint

ASecurity

Scaffold idempotency-key handling for unsafe POSTs — read an Idempotency-Key header, replay the stored response on a retry instead of re-processing, otherwise process once and store the response keyed by (key, request fingerprint). Ships a servlet filter plus a storage SPI the project implements with Redis or a DB. Trigger phrases: "idempotency key", "idempotent endpoint", "make POST idempotent", "safe retries", "exactly-once POST", "dedupe requests".

  • 10 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added August 31, 2026
developmentjavaspring

Works with

  • cli

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned August 31, 2026

npx -y skills add ShipWithAI/shipwithai-plugins --skill idempotent-endpoint --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Idempotent Endpoint?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Idempotent Endpoint
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/shipwithai-idempotent-endpoint/badge)](https://www.skillsdirectory.com/skills/shipwithai-idempotent-endpoint)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: idempotent-endpoint
description: >
  Scaffold idempotency-key handling for unsafe POSTs — read an Idempotency-Key header,
  replay the stored response on a retry instead of re-processing, otherwise process
  once and store the response keyed by (key, request fingerprint). Ships a servlet
  filter plus a storage SPI the project implements with Redis or a DB.
  Trigger phrases: "idempotency key", "idempotent endpoint", "make POST idempotent",
  "safe retries", "exactly-once POST", "dedupe requests".
argument-hint: "[base-package]"
---

# Idempotent Endpoint — Scaffold

Unsafe POSTs get retried — by clients, proxies, and message queues. Without
idempotency a retry charges the card twice or creates two orders. This scaffolds a
filter that makes a retry carrying the same `Idempotency-Key` **replay** the original
response, so the side effect happens exactly once.

## Step 1 — Detect conventions (do not assume)

Read before generating:
- **Existing filter chain:** look for `OncePerRequestFilter` / `FilterRegistrationBean`
  config and a `…​.web` / `…​.config` package; place the filter there and register it
  the same way the project registers other filters.
- **Storage available:** check for Redis (`spring-data-redis`) or a relational DB. The
  filter depends only on the `IdempotencyStore` SPI — pick the backing store that
  already exists; do not add a new datastore.
- **Existing idempotency:** if the project already keys retries somewhere, extend that
  instead of adding a parallel mechanism.

## Step 2 — Render templates

From `assets/`, substitute `{{PACKAGE}}`:

- `IdempotencyStore.java.tmpl` → `<pkg>/web/idempotency/IdempotencyStore.java` (the SPI)
- `IdempotencyKeyFilter.java.tmpl` → `<pkg>/web/idempotency/IdempotencyKeyFilter.java`

The filter logic:
1. Only guards `POST` requests that carry an `Idempotency-Key` header; everything else
   passes straight through.
2. Computes a **fingerprint** = hash of method + URI + body.
3. `store.find(key)`:
   - **hit, same fingerprint** → replay the stored status/body, skip the handler.
   - **hit, different fingerprint** → `422` (the key was reused for a different request).
   - **miss** → run the handler, then `store.save(key, response)`.

## Step 3 — Implement the store

Generate (or point the user to write) one `IdempotencyStore` implementation:
```java
@Component
class RedisIdempotencyStore implements IdempotencyStore {
    // SET key <json> NX EX <ttl>; GET key. Use a short TTL (minutes–hours), not forever.
    // A DB variant: unique column on key + an inserted-at for expiry.
}
```
Register the filter (e.g. a `FilterRegistrationBean<IdempotencyKeyFilter>`) scoped to
the POST routes that need it — not every endpoint.

## Step 4 — Report

```
Created:
  src/main/java/.../web/idempotency/IdempotencyStore.java        (SPI)
  src/main/java/.../web/idempotency/IdempotencyKeyFilter.java    (filter)
  + a store implementation (Redis/DB) — implement before shipping
```

## Failure modes — do NOT

- Do NOT store responses forever — set a TTL; an unbounded store is a memory/disk leak.
- Do NOT replay on a different request body under the same key — return 422 instead.
- Do NOT apply idempotency to safe methods (GET/HEAD) — they are already idempotent.
- Do NOT key only on the header — include a request fingerprint so a reused key can't
  replay an unrelated response.
- Do NOT store the key without scoping it to the caller/tenant if keys aren't globally
  unique in your system.

Files in this skill

  • SKILL.md3.5 KB
  • assets/IdempotencyKeyFilter.java.tmpl5.6 KB
  • assets/IdempotencyStore.java.tmpl1.1 KB
  • evals.json1.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.