Skip to content

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

Description

@ANSHSINGH050404

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
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 (bac6b33)
  • Reproduced against local dev setup (pnpm dev, Next.js 15.5.8)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions