effect-patterns-error-handling-resilience
Implements exponential backoff with jitter to manage retries during service failures and reduce load on failing systems.
Install
mkdir -p .claude/skills/effect-patterns-error-handling-resilience && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/4903" && unzip -o skill.zip -d .claude/skills/effect-patterns-error-handling-resilience && rm skill.zipInstalls to .claude/skills/effect-patterns-error-handling-resilience
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Effect-TS patterns for Error Handling Resilience. Use when working with error handling resilience in Effect-TS applications.Key capabilities
- →Implement exponential backoff
- →Apply jitter to retry attempts
- →Prevent cascading service failures
- →Configure retry limits
How it works
It uses the Effect-TS scheduling module to calculate delays that double with each attempt, adding random jitter to prevent synchronized retry storms.
Inputs & outputs
When to use effect-patterns-error-handling-resilience
- →Implement exponential backoff for API calls
- →Configure retry logic with jitter
- →Prevent cascading failures in services
About this skill
Effect-TS Patterns: Error Handling Resilience
This skill provides 1 curated Effect-TS patterns for error handling resilience. Use this skill when working on tasks related to:
- error handling resilience
- Best practices in Effect-TS applications
- Real-world patterns and solutions
🟡 Intermediate Patterns
Scheduling Pattern 2: Implement Exponential Backoff for Retries
Rule: Use exponential backoff with jitter for retries to prevent overwhelming failing services and improve success likelihood through smart timing.
Good Example:
This example demonstrates exponential backoff with jitter for retrying a flaky API call.
import { Effect, Schedule } from "effect";
interface RetryStats {
readonly attempt: number;
readonly delay: number;
readonly lastError?: Error;
}
// Simulate flaky API that fails first 3 times, succeeds on 4th
let attemptCount = 0;
const flakyApiCall = (): Effect.Effect<{ status: string }> =>
Effect.gen(function* () {
attemptCount++;
yield* Effect.log(`[API] Attempt ${attemptCount}`);
if (attemptCount < 4) {
yield* Effect.fail(new Error("Service temporarily unavailable (503)"));
}
return { status: "ok" };
});
// Calculate exponential backoff with jitter
interface BackoffConfig {
readonly baseDelayMs: number;
readonly maxDelayMs: number;
readonly maxRetries: number;
}
const exponentialBackoffWithJitter = (config: BackoffConfig) => {
let attempt = 0;
// Calculate delay for this attempt
const calculateDelay = (): number => {
const exponential = config.baseDelayMs * Math.pow(2, attempt);
const withJitter = exponential * (0.5 + Math.random() * 0.5); // ±50% jitter
const capped = Math.min(withJitter, config.maxDelayMs);
yield* Effect.log(
`[BACKOFF] Attempt ${attempt + 1}: ${Math.round(capped)}ms delay`
);
return Math.round(capped);
};
return Effect.gen(function* () {
const effect = flakyApiCall();
let lastError: Error | undefined;
for (attempt = 0; attempt < config.maxRetries; attempt++) {
const result = yield* effect.pipe(Effect.either);
if (result._tag === "Right") {
yield* Effect.log(`[SUCCESS] Succeeded on attempt ${attempt + 1}`);
return result.right;
}
lastError = result.left;
if (attempt < config.maxRetries - 1) {
const delay = calculateDelay();
yield* Effect.sleep(`${delay} millis`);
}
}
yield* Effect.log(
`[FAILURE] All ${config.maxRetries} attempts exhausted`
);
yield* Effect.fail(lastError);
});
};
// Run with exponential backoff
const program = exponentialBackoffWithJitter({
baseDelayMs: 100,
maxDelayMs: 5000,
maxRetries: 5,
});
console.log(
`\n[START] Retrying flaky API with exponential backoff\n`
);
Effect.runPromise(program).then(
(result) => console.log(`\n[RESULT] ${JSON.stringify(result)}\n`),
(error) => console.error(`\n[ERROR] ${error.message}\n`)
);
Output demonstrates increasing delays with jitter:
[START] Retrying flaky API with exponential backoff
[API] Attempt 1
[BACKOFF] Attempt 1: 78ms delay
[API] Attempt 2
[BACKOFF] Attempt 2: 192ms delay
[API] Attempt 3
[BACKOFF] Attempt 3: 356ms delay
[API] Attempt 4
[SUCCESS] Succeeded on attempt 4
[RESULT] {"status":"ok"}
Rationale:
When retrying failed operations, use exponential backoff with jitter: delay doubles on each retry (with random jitter), up to a maximum. This prevents:
- Thundering herd: All clients retrying simultaneously
- Cascade failures: Overwhelming a recovering service
- Resource exhaustion: Too many queued retry attempts
Formula: delay = min(maxDelay, baseDelay * 2^attempt + random_jitter)
Naive retry strategies fail under load:
Immediate retry:
- All failures retry at once
- Fails service under load (recovery takes longer)
- Leads to cascade failure
Fixed backoff (e.g., 1 second always):
- No pressure reduction during recovery
- Multiple clients cause thundering herd
- Predictable = synchronized retries
Exponential backoff:
- Gives failing service time to recover
- Each retry waits progressively longer
- Without jitter, synchronized retries still hammer service
Exponential backoff + jitter:
- Spreads retry attempts over time
- Failures de-correlate across clients
- Service recovery time properly utilized
- Success likelihood increases with each retry
Real-world example: 100 clients fail simultaneously
- Immediate retry: 100 requests in milliseconds → failure
- Fixed backoff: 100 requests at exactly 1s → failure
- Exponential: 100 requests at 100ms, 200ms, 400ms, 800ms → recovery → success
When not to use it
- →When the operation is not idempotent
- →When immediate failure is preferred over retries
Prerequisites
Limitations
- →Requires careful tuning of base delay and max retries
- →Only effective for transient service failures
How it compares
It uses a declarative scheduling approach to manage retries instead of manual loop-based logic.
Compared to similar skills
effect-patterns-error-handling-resilience side by side with the closest alternatives in the catalog.
Try saying
Example prompts that trigger this skill in your AI assistant.
More by PaulJPhilp
View all by PaulJPhilp →You might also like
types
sidorares
Comprehensive reference for fixing TypeScript types in mysql2 `.mts` test files and guiding the `/lib` → TypeScript conversion. Trained on all `.d.ts` files in `/typings`.
fix-ts
frozar
1. Run `npx tsc --noEmit` to get all errors 2. Fix each error across all affected files — NEVER use `any`. Use proper types, generics, or `unknown` with type guards. 3. After all fixes, re-run `npx tsc --noEmit` and confirm zero errors 4. Run `npx vitest run` to confirm no test r
run
diana-uk
Run TypeScript solution against test cases. Use when user wants to test their code.
drizzle
lobehub
Drizzle ORM schema and database guide. Use when working with database schemas (src/database/schemas/*), defining tables, creating migrations, or database model code. Triggers on Drizzle schema definition, database migrations, or ORM usage questions.
zustand
lobehub
Zustand state management guide. Use when working with store code (src/store/**), implementing actions, managing state, or creating slices. Triggers on Zustand store development, state management questions, or action implementation.
motion-canvas
davila7
Complete production-ready guide for Motion Canvas with ESM/CommonJS workarounds, full setup templates, and troubleshooting for programmatic video creation using TypeScript