lru-queue
lru-queue is a low-level CommonJS helper that tracks recency for a fixed number of string identifiers. Calling hit(id) marks an identifier as most recently used and, when the limit is exceeded, returns the least recently used identifier so your code can evict the corresponding value from a separate cache. delete(id) forgets one identifier and clear() resets all recency state. It stores no values, exposes no reads or iteration, and was created to support memoizee's bounded-cache option.
Do not install lru-queue for a new cache. It remains acceptable as a pinned internal dependency for memoizee-compatible code, but most applications should use a maintained cache that owns values and exposes modern safeguards.
Use it if
- You maintain code already using memoizee-style separate value storage and only need its recency bookkeeping contract
- Your cache keys are plain strings and you want hit to return exactly the identifier to evict
- You need a tiny synchronous CommonJS queue with only hit, delete, and clear operations
- You can pin an unchanged 0.1.0 dependency and cover its behavior with your own tests
- You are building a new cache: lru-cache stores values, supports modern modules and TypeScript, and exposes size, TTL, disposal, fetch, and iteration controls
- Your keys are objects, symbols, numbers with distinct type identity, or compound values; the README requires plain strings and the implementation uses object-property maps
- You need TTL expiry, stale reads, maximum weight, async loading, disposal callbacks, statistics, peek, or iteration; none exists here
- You want ESM or TypeScript declarations: version 0.1.0 is a CommonJS module with no bundled types and README browser advice still names Browserify and Webmake
- You require active maintenance: 0.1.0 was published in April 2014 and the repository's last code push was December 2022
Setup reality
npm install lru-queue installs a CommonJS package whose only runtime dependency is es5-ext. The published version is still 0.1.0 from April 2014. Use require('lru-queue') unless your ESM runtime's CommonJS interop supplies a default import; there is no native exports map or TypeScript declaration. Calling the factory with a limit returns an opaque object with hit, delete, and clear. It does not store cached values, report its size, tell you whether an identifier is present, or let you iterate the order. Your code must maintain a separate Map or object and delete the value whose identifier hit returns. The README says identifiers must be plain strings. Passing numbers may appear to work through property coercion but collapses key identity, and object keys become string representations, so do not stretch the contract. The limit is normalized through es5-ext's positive-integer helper rather than validated with a descriptive application error; validate configuration before constructing the queue. Re-hitting an existing identifier moves it to most-recent position and returns undefined. A new identifier beyond capacity returns the evicted identifier, but the queue cannot evict your value automatically. delete silently does nothing for a missing identifier, and clear does not notify you which external values to drop. Browser use requires bundling CommonJS, despite the README's dated browser-tool suggestions. There are no timers or asynchronous behavior, so one queue should remain owned by a single JavaScript process; it is not a distributed cache policy. For new work, lru-cache or quick-lru removes most of this bookkeeping and has current releases, typings, module support, and a much clearer maintenance story.
Patterns
Create a fixed-limit recency queuecreate-recency-queue
const createLruQueue = require('lru-queue')
const queue = createLruQueue(3)
queue.hit('alpha')
queue.hit('beta')
queue.hit('gamma')The queue tracks identifiers only. It does not store values or expose its current size.
Evict from a separate value Mapevict-external-cache
const values = new Map()
function cacheSet(id, value) {
values.set(id, value)
const evictedId = queue.hit(id)
if (evictedId !== undefined) values.delete(evictedId)
}Always delete the returned identifier from the external store or its contents drift from the recency queue.
Mark a successful read as recentrefresh-cache-hit
function cacheGet(id) {
if (!values.has(id)) return undefined
queue.hit(id)
return values.get(id)
}Only call hit for entries that actually exist in the external value store.
Delete recency and value state togetherremove-cache-entry
function cacheDelete(id) {
queue.delete(id)
return values.delete(id)
}queue.delete returns no presence result, so use the external Map when callers need a Boolean.
Clear both layers of a cacheclear-cache-state
function cacheClear() {
queue.clear()
values.clear()
}Clearing only the queue leaves stale values; clearing only the Map leaves stale recency identifiers.
Update a value and refresh its recencyupdate-existing-entry
function cacheUpdate(id, update) {
if (!values.has(id)) return false
values.set(id, update(values.get(id)))
queue.hit(id)
return true
}Re-hitting an existing identifier moves it to the newest position without evicting another entry.
Validate the limit before constructionvalidate-queue-limit
function makeQueue(limit) {
if (!Number.isSafeInteger(limit) || limit < 1) {
throw new RangeError('cache limit must be a positive integer')
}
return createLruQueue(limit)
}The package normalizes through es5-ext; validating first produces an application-specific failure instead of surprising capacity.
Encode typed identities as plain stringsnamespace-string-keys
function userKey(id) {
return `user:${id}`
}
function orderKey(id) {
return `order:${id}`
}
cacheSet(userKey(42), user)
cacheSet(orderKey(42), order)The documented identifier contract is plain strings; namespaces prevent unrelated numeric IDs from colliding.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| lru-cache | npm | You want a maintained full cache with values, TTL, size tracking, disposal hooks, async fetch, ESM, and TypeScript |
| quick-lru | npm | You want a small modern Map-like LRU for straightforward bounded caching |
| mnemonist | npm | You need a collection library that includes LRUCache and many other tested data structures |