← Back to PRs

#10280: fix(infra): add max size limit to Tailscale whois cache to prevent memory leak

by programming-pupil open 2026-02-06 09:09 View on GitHub →
stale
## Problem The `whoisCache` in `src/infra/tailscale.ts` is a global `Map` that only has TTL-based expiration but no size limit: ```typescript const whoisCache = new Map<string, TailscaleWhoisCacheEntry>(); ``` If a gateway handles requests from many different IP addresses over time, the cache will grow unbounded, potentially causing memory issues in long-running processes. ## Comparison The same codebase already implements proper bounded caching in `src/infra/dedupe.ts`: ```typescript export function createDedupeCache(options: DedupeCacheOptions): DedupeCache { const ttlMs = Math.max(0, options.ttlMs); const maxSize = Math.max(0, Math.floor(options.maxSize)); // Has maxSize! // ... while (cache.size > maxSize) { const oldestKey = cache.keys().next().value; if (!oldestKey) break; cache.delete(oldestKey); } } ``` ## Solution Add a `WHOIS_CACHE_MAX_SIZE` constant (default 1000) and enforce it in `writeCachedWhois`: 1. When cache reaches max size, first prune expired entries 2. If still over limit, evict oldest entries (LRU-style, leveraging Map insertion order) 3. Then insert the new entry This ensures the cache stays bounded while maintaining the existing TTL behavior. ## Impact - Prevents unbounded memory growth in long-running gateway processes - Consistent with existing caching patterns in the codebase - No behavioral change for normal usage (1000 entries is generous for typical deployments) <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> - Adds a fixed maximum size (`WHOIS_CACHE_MAX_SIZE = 1000`) to the global `whoisCache` in `src/infra/tailscale.ts`. - On write, prunes expired entries and then evicts the oldest `Map` entries until under the limit. - Intends to prevent unbounded memory growth in long-running gateway processes while keeping TTL-based caching semantics. <h3>Confidence Score: 4/5</h3> - This PR is likely safe to merge, but the current eviction behavior is mislabeled and may cause unexpected cache churn. - Change is localized and prevents unbounded growth, but the implementation does FIFO/oldest-insert eviction rather than true LRU as documented in-code, which can lead to higher miss rates than expected under repeated access patterns. - src/infra/tailscale.ts <!-- greptile_other_comments_section --> <sub>(5/5) You can turn off certain types of comments like style [here](https://app.greptile.com/review/github)!</sub> <!-- /greptile_comment -->

Most Similar PRs