API timeouts and missed webhooks happen when backend handlers wait synchronously on external third-party services that experience latency spikes. Wrapping external calls in explicit AbortController timeouts, implementing exponential backoff retries, and designing idempotent webhook ingestion ensures systems never drop critical transactions.
Targeted Code Solution
lib/resilientFetch.tslib/resilientFetch.tstypescript
export async function fetchWithRetry(
url: string,
options: RequestInit = {},
retries = 3,
backoffMs = 1000
): Promise<Response> {
const timeoutMs = 8000;
for (let attempt = 1; attempt <= retries; attempt++) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(url, {
...options,
signal: controller.signal,
});
clearTimeout(timeoutId);
// Do not retry client 4xx errors; retry server 5xx errors
if (response.ok || (response.status >= 400 && response.status < 500)) {
return response;
}
} catch (err: any) {
clearTimeout(timeoutId);
if (attempt === retries) throw err;
}
// Exponential backoff delay with jitter
const delay = backoffMs * Math.pow(2, attempt - 1) + Math.random() * 200;
await new Promise((resolve) => setTimeout(resolve, delay));
}
throw new Error(`Failed to fetch ${url} after ${retries} attempts`);
}
Need this resolved on your app?
If this error is blocking your release build or production pipeline, Syed Alijah Muhammad can diagnose and deploy a clean fix. Send the repository access, error trace, and platform details.