From harness-claude
Implements retry logic with exponential backoff and jitter for handling transient failures in network requests, database connections, and rate-limited APIs. Provides a reusable `withRetry` utility with configurable max attempts, shouldRetry predicate, and onRetry callback.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:resilience-retry-patternThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Handle transient failures with configurable retry strategies, exponential backoff, and jitter
Handle transient failures with configurable retry strategies, exponential backoff, and jitter
delay = baseDelay * 2^attempt. This prevents thundering herd.delay = baseDelay * 2^attempt * (0.5 + random()). This spreads retry storms.// utils/retry.ts
interface RetryOptions {
maxAttempts: number;
baseDelay: number;
maxDelay: number;
shouldRetry?: (error: unknown, attempt: number) => boolean;
onRetry?: (error: unknown, attempt: number, delay: number) => void;
}
const DEFAULT_OPTIONS: RetryOptions = {
maxAttempts: 3,
baseDelay: 1000,
maxDelay: 30000,
shouldRetry: () => true,
};
export async function withRetry<T>(
fn: () => Promise<T>,
options: Partial<RetryOptions> = {}
): Promise<T> {
const opts = { ...DEFAULT_OPTIONS, ...options };
let lastError: unknown;
for (let attempt = 0; attempt < opts.maxAttempts; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error;
if (attempt === opts.maxAttempts - 1) break;
if (!opts.shouldRetry!(error, attempt)) break;
// Exponential backoff with full jitter
const exponentialDelay = opts.baseDelay * Math.pow(2, attempt);
const jitter = Math.random();
const delay = Math.min(exponentialDelay * jitter, opts.maxDelay);
opts.onRetry?.(error, attempt + 1, delay);
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
throw lastError;
}
// Usage
import { withRetry } from './utils/retry';
const user = await withRetry(
() =>
fetch('/api/users/123').then((r) => {
if (!r.ok) throw new Error(`HTTP ${r.status}`);
return r.json();
}),
{
maxAttempts: 3,
baseDelay: 1000,
shouldRetry: (error) => {
if (error instanceof Error && error.message.includes('HTTP 4')) return false;
return true; // Retry 5xx and network errors
},
onRetry: (error, attempt, delay) => {
console.warn(`Retry ${attempt} after ${delay}ms: ${error}`);
},
}
);
Backoff strategies:
delay = baseDelay * attempt. Gentle ramp-up.delay = baseDelay * 2^attempt. Standard for APIs.Jitter types:
random(0, baseDelay * 2^attempt) — most spread, lowest contentionbaseDelay * 2^attempt / 2 + random(0, baseDelay * 2^attempt / 2) — guaranteed minimum waitmin(maxDelay, random(baseDelay, prevDelay * 3)) — Amazon recommendationRetry-After header: Some APIs return Retry-After with 429 or 503 responses. Always respect this header over your calculated backoff.
What NOT to retry:
Libraries: p-retry, async-retry, cockatiel (composable policies), axios-retry.
https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeGuides API design for retry behavior: classifying transient vs permanent errors, emitting Retry-After headers, and implementing exponential backoff with jitter to prevent retry storms.
Generates PHP 8.4 retry pattern infrastructure with exponential backoff, jitter, configurable strategies for transient failures in APIs, databases, and queues. Includes unit tests.
Implements Python resilience patterns: retries with tenacity, exponential backoff, jitter, timeouts, and decorators. For fault-tolerant services handling transient failures and network issues.