#4267·dub

Deleted / re-keyed links keep redirecting for ~5s due to stale in-process LRU cache

Author: ANSHSINGH050404Created Aug 3, 2026Updated Aug 20, 2026

Summary linkCache.delete() (and deleteMany/expireMany) only remove the link from Redis and the Vercel runtime cache — they never purge the in-process LRUCache in apps/web/lib/api/links/cache.ts. Since linkCache.get() serves the LRU first (10k entries, 5s TTL), a link that was deleted, or whose key/domain was changed, continues to resolve to its old destination for up to 5 seconds per server instance. Files involved

  • apps/web/lib/api/links/cache.ts — get() (LRU-first) and delete()/deleteMany()/expireMany() (Redis/Vercel only)
  • apps/web/lib/api/links/update-link.ts:203 — linkCache.delete(oldLink) on key/domain change
  • apps/web/lib/api/links/delete-link.ts:59 — linkCache.delete(link) on delete // cache.ts — get() checks LRU first, delete() never clears it
typescript
async get({ domain, key }) {
  let cachedLink = linkLRUCache.get(cacheKey) || null;   // <-- stale hit possible
  ...
}
async delete({ domain, key }) {
  const cacheKey = this._createKey({ domain, key });
  waitUntil(this._invalidateVercelRuntimeCache(cacheKey));
  return await redisGlobal.del(cacheKey);                // <-- LRU untouched
}

Expected behavior Once a link is deleted or its key is changed, the old short link stops resolving immediately. Actual behavior The old short link keeps redirecting to the old destination for up to ~5 seconds (the LRU TTL), because linkCache.delete() doesn't invalidate the in-process linkLRUCache. Impact Users see deleted links keep working and old keys still redirect after an edit. Every delete/key-edit on a hot link hits this window; the delete+recreate variant can transiently break the new link. Suggested direction Have delete()/deleteMany()/expireMany() also linkLRUCache.delete(cacheKey) (same as set() does on write), or version the LRU entries so post-mutation reads bypass them. Environment

  • dub monorepo @ main (bac6b33104)
  • Reproduced against local dev setup (pnpm dev, Next.js 15.5.8)