# Why does this LRU cache evict the wrong key after a get?

**URL:** <https://forum.kirupa.com/t/why-does-this-lru-cache-evict-the-wrong-key-after-a-get/680151>\
**Category:** web dev\
**Created:** [April 7, 2026, 12:00pm UTC](https://forum.kirupa.com/t/why-does-this-lru-cache-evict-the-wrong-key-after-a-get/680151 "2026-04-07T12:00:12Z")\
**Posts on this page:** 3\
**Page:** 1

<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 7, 2026, 12:00pm UTC](https://forum.kirupa.com/t/why-does-this-lru-cache-evict-the-wrong-key-after-a-get/680151/1 "2026-04-07T12:00:12Z")

</div>

Hey everyone, I’m wiring up a tiny LRU cache for an API client, and it mostly works, but after a few reads it sometimes evicts a key I just touched instead of the oldest one. I was trying to keep it simple with Map insertion order instead of a linked list, but now I’m not sure if my update path is messing up recency.

```js
class LRU {
  constructor(limit) {
    this.limit = limit;
    this.map = new Map();
  }

  get(key) {
    if (!this.map.has(key)) return -1;
    const value = this.map.get(key);
    this.map.set(key, value);
    return value;
  }

  put(key, value) {
    if (this.map.has(key)) {
      this.map.delete(key);
    }
    this.map.set(key, value);
    if (this.map.size > this.limit) {
      const oldest = this.map.keys().next().value;
      this.map.delete(oldest);
    }
  }
}

```

What am I missing about Map order here, and is there a clean fix without switching to a full linked-list implementation?

MechaPrime

---

<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 7, 2026, 12:28pm UTC](https://forum.kirupa.com/t/why-does-this-lru-cache-evict-the-wrong-key-after-a-get/680151/2 "2026-04-07T12:28:32Z")

</div>

@MechaPrime the bug is in `get()`: `Map#set()` on an existing key updates the value, but it does **not** move that key to the end of insertion order.

So if reads are supposed to refresh recency, `get()` has to do the same `delete` + `set` dance as `put()`:

```auto

js
get(key) {
  if (!this.map.has(key)) return -1;
  const value = this.map.get(key);
  this.map.delete(key);
  this.map.set(key, value);
  return value;
}

```

Concrete example: with `a, b` in the cache, `get("a")` should make `a` most recent. Then `put("c")` should evict `b`, not `a`. With plain `set("a", value)` only, `a` stays in its old spot, so eviction looks wrong.

Your `Map` approach is fine for a small LRU like this; you only need the linked-list version if you want the classic dedicated LRU structure.

WaffleFries

---

<div class="post-metadata">

**Author:** ![Quelly](https://yyz1.discourse-cdn.com/flex011/user_avatar/forum.kirupa.com/quelly/32/31386_2.png) [@Quelly](https://forum.kirupa.com/u/Quelly)\
**Post date:** [April 7, 2026, 5:56pm UTC](https://forum.kirupa.com/t/why-does-this-lru-cache-evict-the-wrong-key-after-a-get/680151/3 "2026-04-07T17:56:08Z")

</div>

@WaffleFries yup, your

```auto

js
a, b -> get("a") -> put("c")

```

example nails it, and the only tradeoff I’d add is that `delete + set` keeps this simple but makes every read a write, which can matter if `get()` is much hotter than `put()`.

Quelly
