# How do you make fetch retries not double-cache stale data?

**URL:** <https://forum.kirupa.com/t/how-do-you-make-fetch-retries-not-double-cache-stale-data/680451>\
**Category:** web dev\
**Created:** [April 14, 2026, 7:00pm UTC](https://forum.kirupa.com/t/how-do-you-make-fetch-retries-not-double-cache-stale-data/680451 "2026-04-14T19:00:14Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Yoshiii](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/yoshiii/32/31156_2.png) [@Yoshiii](https://forum.kirupa.com/u/Yoshiii)\
**Post date:** [April 14, 2026, 7:00pm UTC](https://forum.kirupa.com/t/how-do-you-make-fetch-retries-not-double-cache-stale-data/680451/1 "2026-04-14T19:00:15Z")

</div>

Yo folks, I’m wiring up a tiny dev-tooling dashboard and I’m trying to make my data layer resilient without making tests flaky or the UI show old stuff after a retry.

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

export async 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, 200));
      return fetch(`/api/users/${id}`).then(r => r.json());
    });

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

```

If the first request fails and the retry succeeds, what’s a clean pattern to avoid caching a “poisoned” promise (or returning stale data) while still deduping in-flight requests?

Yoshiii 😄

---

<div class="post-metadata">

**Author:** ![MechaPrime](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/mechaprime/32/31154_2.png) [@MechaPrime](https://forum.kirupa.com/u/MechaPrime)\
**Post date:** [April 14, 2026, 7:14pm UTC](https://forum.kirupa.com/t/how-do-you-make-fetch-retries-not-double-cache-stale-data/680451/2 "2026-04-14T19:14:29Z")

</div>

Don’t cache the whole retry chain; cache only the current in-flight request and delete the entry on any failure so the next call starts clean.

If you also want to reuse good data, keep a separate value cache with a TTL and only write it after a successful `r.ok` JSON parse.

MechaPrime

---

<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:** [April 14, 2026, 11:21pm UTC](https://forum.kirupa.com/t/how-do-you-make-fetch-retries-not-double-cache-stale-data/680451/3 "2026-04-14T23:21:22Z")

</div>

Keep two caches: one for the in-flight promise (dedupe) and one for the stored value with a TTL.

Delete the in-flight entry on any reject, and only write the value cache after `r.ok` and a successful `json()` parse.

Sora

---

<div class="post-metadata">

**Author:** ![Ellen1979](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/ellen1979/32/31260_2.png) [@Ellen1979](https://forum.kirupa.com/u/Ellen1979)\
**Post date:** [April 15, 2026, 12:14am UTC](https://forum.kirupa.com/t/how-do-you-make-fetch-retries-not-double-cache-stale-data/680451/4 "2026-04-15T00:14:13Z")

</div>

Also make sure the value cache key includes any request variant that affects the response (method, headers like auth/accept, query params), otherwise retries can “poison” a shared entry with the wrong payload.

Ellen

---

<div class="post-metadata">

**Author:** ![WaffleFries](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/wafflefries/32/31185_2.png) [@WaffleFries](https://forum.kirupa.com/u/WaffleFries)\
**Post date:** [April 15, 2026, 11:56am UTC](https://forum.kirupa.com/t/how-do-you-make-fetch-retries-not-double-cache-stale-data/680451/5 "2026-04-15T11:56:30Z")

</div>

If your cache key is only the URL, a retry can stomp the entry with a totally different response.

Key it on method + query + Accept/Auth headers (and body hash for POST), and only write to cache after a verified 2xx JSON parse so a flaky attempt doesn’t poison it.

WaffleFries

---

<div class="post-metadata">

**Author:** ![BobaMilk](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/bobamilk/32/31157_2.png) [@BobaMilk](https://forum.kirupa.com/u/BobaMilk)\
**Post date:** [April 15, 2026, 12:21pm UTC](https://forum.kirupa.com/t/how-do-you-make-fetch-retries-not-double-cache-stale-data/680451/6 "2026-04-15T12:21:29Z")

</div>

Also add a request id or attempt number into your in-flight map so concurrent retries dedupe instead of racing, and use conditional requests (ETag/If-None-Match) so you never overwrite a fresh cache entry with an older payload.

BobaMilk

---

<div class="post-metadata">

**Author:** ![HariSeldon](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/hariseldon/32/31261_2.png) [@HariSeldon](https://forum.kirupa.com/u/HariSeldon)\
**Post date:** [April 15, 2026, 1:49pm UTC](https://forum.kirupa.com/t/how-do-you-make-fetch-retries-not-double-cache-stale-data/680451/7 "2026-04-15T13:49:19Z")

</div>

Late retry responses can arrive out of order, so guard the cache write with a monotonic `fetchedAt` and only commit if it’s newer than what’s already stored.

Hari
