From harness-claude
Implements idempotency for API endpoints and message consumers to safely handle retries without duplicate side effects.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:resilience-idempotencyThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Ensure safe retries by making operations produce the same result regardless of how many times they execute
Ensure safe retries by making operations produce the same result regardless of how many times they execute
Idempotency-Key header on non-idempotent endpoints (POST, PATCH). The client generates a unique key per logical operation.// middleware/idempotency.ts
interface StoredResponse {
statusCode: number;
body: unknown;
headers: Record<string, string>;
createdAt: number;
}
export class IdempotencyStore {
constructor(
private redis: Redis,
private ttlSeconds: number = 86400 // 24 hours
) {}
async check(key: string): Promise<StoredResponse | null> {
const data = await this.redis.get(`idem:${key}`);
return data ? JSON.parse(data) : null;
}
async lock(key: string): Promise<boolean> {
// Set NX — only succeeds if key does not exist
const result = await this.redis.set(`idem:lock:${key}`, '1', 'EX', 60, 'NX');
return result === 'OK';
}
async store(key: string, response: StoredResponse): Promise<void> {
await this.redis.setex(`idem:${key}`, this.ttlSeconds, JSON.stringify(response));
await this.redis.del(`idem:lock:${key}`);
}
async unlock(key: string): Promise<void> {
await this.redis.del(`idem:lock:${key}`);
}
}
// Express middleware
export function idempotencyMiddleware(store: IdempotencyStore) {
return async (req: Request, res: Response, next: NextFunction) => {
const key = req.headers['idempotency-key'] as string;
if (!key) return next(); // No key = no idempotency protection
// Check for cached response
const cached = await store.check(key);
if (cached) {
Object.entries(cached.headers).forEach(([k, v]) => res.setHeader(k, v));
return res.status(cached.statusCode).json(cached.body);
}
// Acquire lock to prevent concurrent processing
const locked = await store.lock(key);
if (!locked) {
return res.status(409).json({ error: 'Request is being processed' });
}
// Intercept the response to store it
const originalJson = res.json.bind(res);
res.json = (body: unknown) => {
store.store(key, {
statusCode: res.statusCode,
body,
headers: { 'content-type': 'application/json' },
createdAt: Date.now(),
});
return originalJson(body);
};
next();
};
}
// Client-side usage
const idempotencyKey = crypto.randomUUID();
const response = await fetch('/api/payments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Idempotency-Key': idempotencyKey,
},
body: JSON.stringify({ amount: 1000, currency: 'usd' }),
});
// Safe to retry with the same key — will get the same response
Naturally idempotent operations: GET, PUT, DELETE are idempotent by HTTP semantics. PUT /users/123 { name: "Alice" } always produces the same result. POST is not naturally idempotent — creating a resource twice creates two resources.
Database-level idempotency: Use unique constraints and upserts:
-- Instead of INSERT (which fails on duplicate)
INSERT INTO orders (idempotency_key, user_id, amount)
VALUES ($1, $2, $3)
ON CONFLICT (idempotency_key) DO NOTHING
RETURNING *;
Message deduplication:
async function processMessage(message: QueueMessage): Promise<void> {
const messageId = message.id;
const processed = await redis.set(`msg:${messageId}`, '1', 'EX', 3600, 'NX');
if (!processed) {
console.log(`Duplicate message ${messageId}, skipping`);
return;
}
await handleMessage(message.body);
}
Key generation strategies:
Edge cases:
https://stripe.com/docs/api/idempotent_requests
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeHandles duplicate message delivery safely using idempotency keys and deduplication stores. Useful for at-least-once message delivery systems, payment processing, and retry logic.
Implements idempotent API operations with keys, Redis response caching, and DB constraints for safe retries in payments, webhooks, or duplicate processing.
Provides patterns for designing idempotent APIs with keys to handle retries safely, prevent duplicates, and ensure at-most-once semantics in payments/orders.