بنقرة واحدة
effect-patterns-error-handling-resilience
// Effect-TS patterns for Error Handling Resilience. Use when working with error handling resilience in Effect-TS applications.
// Effect-TS patterns for Error Handling Resilience. Use when working with error handling resilience in Effect-TS applications.
Effect-TS service and agent patterns for this repo. Use when implementing or modifying services in packages/mcp-server, adding agents, or following Effect.Service, Layer, and error-handling conventions.
Effect-TS patterns for Core Concepts. Use when working with core concepts in Effect-TS applications.
Effect-TS patterns for Building Apis. Use when working with building apis in Effect-TS applications.
Effect-TS patterns for Building Data Pipelines. Use when working with building data pipelines in Effect-TS applications.
Effect-TS patterns for Concurrency Getting Started. Use when working with concurrency getting started in Effect-TS applications.
Effect-TS patterns for Concurrency. Use when working with concurrency in Effect-TS applications.
| name | effect-patterns-error-handling-resilience |
| description | Effect-TS patterns for Error Handling Resilience. Use when working with error handling resilience in Effect-TS applications. |
This skill provides 1 curated Effect-TS patterns for error handling resilience. Use this skill when working on tasks related to:
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:
Formula: delay = min(maxDelay, baseDelay * 2^attempt + random_jitter)
Naive retry strategies fail under load:
Immediate retry:
Fixed backoff (e.g., 1 second always):
Exponential backoff:
Exponential backoff + jitter:
Real-world example: 100 clients fail simultaneously