Skip to content

[Bug] pruneMemoryBuckets only removes empty keys stale timestamps within active keys accumulate indefinitely #1477

@Midoriya-w

Description

@Midoriya-w

This issue is raised as part of GSSoC'26. Kindly consider assigning it to me.

Summary

In src/middleware.ts, the pruneMemoryBuckets function only removes
keys where ALL timestamps have expired:

if (active.length === 0) {
memoryBuckets.delete(key);
}

Keys with even one active timestamp are never cleaned of their
older stale timestamps during pruning. Over time, a frequently
accessed key accumulates thousands of stale timestamps that are
filtered out on every request but never actually removed from memory.

Additionally, pruning is skipped entirely when the map has fewer
than 500 keys, so per-key memory growth happens invisibly in
low-traffic scenarios.

Steps to Reproduce

  1. Make 1000+ requests from the same IP over multiple windows
  2. Inspect memoryBuckets — the key still holds all old timestamps
  3. Pruning never removes stale timestamps within active keys

Expected Behavior

Stale timestamps within active keys should be cleaned up during
the pruning pass, not just keys with zero active timestamps.

Actual Behavior

Active keys accumulate stale timestamps indefinitely, causing
silent per-key memory growth.

Fix

Update the pruning logic to always clean stale timestamps from
active keys, not just delete empty ones:

for (const [key, values] of Array.from(memoryBuckets.entries())) {
const active = values.filter(
(timestamp: number) => timestamp > cutoff
);
if (active.length === 0) {
memoryBuckets.delete(key);
} else {
memoryBuckets.set(key, active); // always update, not just delete
}
}

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingneeds-triageNeeds maintainer triage

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions