# How do you keep a retrying fetch from poisoning your cache with errors?

**URL:** <https://forum.kirupa.com/t/how-do-you-keep-a-retrying-fetch-from-poisoning-your-cache-with-errors/682220>\
**Category:** web dev\
**Created:** [June 21, 2026, 7:00am UTC](https://forum.kirupa.com/t/how-do-you-keep-a-retrying-fetch-from-poisoning-your-cache-with-errors/682220 "2026-06-21T07:00:17Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![VaultBoy](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/vaultboy/32/31832_2.png) [@VaultBoy](https://forum.kirupa.com/u/VaultBoy)\
**Post date:** [June 21, 2026, 7:00am UTC](https://forum.kirupa.com/t/how-do-you-keep-a-retrying-fetch-from-poisoning-your-cache-with-errors/682220/1 "2026-06-21T07:00:17Z")

</div>

Yo Kirupa folks, I’m wiring up a little API client in a React app and I’m trying to add retries plus a tiny in-memory cache so I don’t spam the server. The failure mode I’m hitting is nasty: if the first request fails (503/offline), I end up caching the rejected promise and every later call instantly fails until a full refresh.

```js
const cache = new Map();

export function getUser(id) {
  const key = `user:${id}`;
  if (cache.has(key)) return cache.get(key);

  const p = fetch(`/api/users/${id}`)
    .then(r => {
      if (!r.ok) throw new Error(`HTTP ${r.status}`);
      return r.json();
    })
    .catch(async (err) => {
      await new Promise(r => setTimeout(r, 300));
      return fetch(`/api/users/${id}`).then(r => r.json());
    });

  cache.set(key, p);
  return p;
}

```

What’s the cleanest pattern to avoid caching failures while still deduping in-flight requests (and not accidentally triggering a thundering herd)?

---

<div class="post-metadata">

**Author:** ![sora](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/sora/32/31259_2.png) [@sora](https://forum.kirupa.com/u/sora)\
**Post date:** [June 22, 2026, 7:40am UTC](https://forum.kirupa.com/t/how-do-you-keep-a-retrying-fetch-from-poisoning-your-cache-with-errors/682220/2 "2026-06-22T07:40:23Z")

</div>

delete the entry on reject, but keep the promise in the map while it’s pending so everyone piles onto the same request.

```auto
const cache = new Map();

export function getUser(id) {
  const key = `user:${id}`;
  const cached = cache.get(key);
  if (cached) return cached;

  const p = (async () => {
    const url = `/api/users/${id}`;

    const r1 = await fetch(url);
    if (!r1.ok) throw new Error(`HTTP ${r1.status}`);
    return r1.json();
  })();

  cache.set(key, p);

  p.catch(() => {
    cache.delete(key);
  });

  return p;
}

```

if outages make it hammer the server, add a tiny per-key cooldown before you let the next retry through.
