Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Track memory growth from in-process registries and add bounded eviction with metrics

Open
#246 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
22/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
nodejs, typescript

Research direction

Start with src/monitoring/metrics-history.service.ts as the reference for the cap, trim and getRetention() pattern, then read src/rate-limiting/rate-limiter.service.ts around the memoryViolations cap and the in-memory bucket fallback. Next check the WebSocket removal paths in src/dashboard/websocket/connection-manager.service.ts and connection-pool.service.ts, and the retention in src/observability/profiling.service.ts. Done means each registry has a documented bound, emits size and eviction metrics, and passes an extended websocket.stress.spec.ts soak check; this needs maintainer agreement on the approach first.

Written by the indexing model from the issue text.

Description

advanced help wanted performance

Problem

Several services keep in-memory state whose growth is not obviously bounded:

  • src/rate-limiting/rate-limiter.service.ts:614-616 — memoryViolations is capped at 2000 entries, which is good, but the cap is a silent truncation with no metric.
  • src/rate-limiting/rate-limiter.service.ts — in-memory rate-limit buckets when Redis is unavailable. These are keyed by client identifier, so the count scales with the number of distinct clients seen.
  • src/dashboard/websocket/connection-manager.service.ts:148,194 and connection-pool.service.ts:284 — Maps built per connection/session.
  • src/observability/profiling.service.ts — tracks "hot functions" and, per PROFILING.md, retains CPU profiles and heap snapshots.

By contrast, src/monitoring/metrics-history.service.ts gets this right: it caps at MONITORING_HISTORY_MAX_POINTS (default 5760, lines 55-56), trims with slice (lines 108-109), and exposes getRetention() (line 134).

Why it matters

An unbounded Map in a long-lived Node process is a slow leak. It survives until the process restarts, degrades GC performance as it grows, and — for the WebSocket registries — retains connection objects and their associated buffers, which is the classic way a WebSocket server accumulates memory under churn.

The rate-limiter buckets are the most concerning because they are keyed by client identity, so a distributed scan or a large client population grows them without bound.

Suggested Direction

  1. Adopt the metrics-history pattern as the house standard: a configurable max size, explicit trimming, and an accessor exposing the retention parameters. src/monitoring/metrics-history.service.ts is the reference implementation to copy.
  2. Bound each registry:
    • Rate-limit buckets: TTL-based expiry plus a max key count. Evict least-recently-used or oldest when over the cap.
    • WebSocket registries: confirm connections are removed on disconnect. A ConnectionManager that only ever adds is a leak; check every removal path, including abnormal closes.
    • Profiling data: bound retained profiles and snapshots, and drop old heap snapshots aggressively — they are large.
  3. Emit metrics for size and eviction counts. A silent cap (as with memoryViolations) means you cannot distinguish a working eviction policy from data being quietly dropped.
  4. Add a soak test. websocket.stress.spec.ts already exists; extend it to assert memory or registry size stabilises over many connect/disconnect cycles rather than growing linearly.
  5. Consider moving large state to Redis where it must be shared across instances anyway (rate-limit buckets in particular).

Constraints

  • Eviction must not weaken the rate limit — evicting an active client's bucket resets their allowance. Use TTL consistent with the window, not an arbitrary size cap, for security-relevant state.
  • WebSocket disconnects must free resources even when the close is not graceful.
  • Do not retain heap snapshots beyond a short period; they are memory-heavy by nature.
  • Coordinate with the logging-facade issue before adding metrics, so the instrumentation is consistent.

Acceptance Criteria

  • Every in-process registry has a documented bound (max size or TTL).
  • Size and eviction counts are emitted as metrics.
  • A soak test shows registry size stabilising rather than growing linearly.
  • Rate-limit eviction does not reset an active client's window.
  • WebSocket resources are freed on both graceful and abnormal disconnects.
  • getRetention()-style introspection exists for each bounded registry.
Dominant language
TypeScript
Stars
7
Forks
55
Avg merge
1d 17h
Merged PRs (30d)
5

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from SourceXXL/alian_structure-api

All issues in SourceXXL/alian_structure-api

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.