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

Expose rate-limit headers consistently and document the contract

Open
#232 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
30/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
nodejs, typescript

Research direction

Start with the global guard registered at src/app.module.ts:311 and the enforcement logic in src/rate-limiting/rate-limiter.service.ts, then check which headers each path sets today. Resolve the conflict between the README's 100 req/min statement (line 155) and the per-tier variables (lines 239-241) before changing code. Done means headers appear on successful and 429 responses, Retry-After is accurate, docs and CHANGELOG.md are updated, and tests cover both paths.

Written by the indexing model from the issue text.

Description

documentation enhancement help wanted intermediate

Problem

Rate limiting is applied globally via DistributedRateLimitGuard (src/app.module.ts:311), but the response contract is not documented and its consistency across paths is unverified.

The README states "Rate limiting (100 req/min per IP)" (line 155) as a security feature, and separately documents tiered configuration at lines 239-241 (RATE_LIMIT_FREE_PER_MINUTE, RATE_LIMIT_PAID_PER_MINUTE, RATE_LIMIT_ENTERPRISE_PER_MINUTE). Those two statements already disagree — 100/min globally versus per-tier.

src/rate-limiting/rate-limiter.service.ts is the enforcement point and rate-limiting.controller.ts exposes administrative views, but there is no documented guarantee about which headers are set (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, Retry-After), whether all responses carry them, or what a client should do with them.

There is also an unresolved correctness question from the in-memory fallback: when Redis is unavailable, limits become per-process, so a client behind N instances effectively gets N× the allowance, and nothing communicates that.

Why it matters

Clients cannot implement correct retry or backoff behaviour without knowing the contract. Well-behaved SDKs throttle themselves using X-RateLimit-Remaining and honour Retry-After; without documented headers they instead react to 429s, which is worse for everyone. The README's own inconsistency means an integrator cannot tell what to expect.

Suggested Direction

  1. Define the header contract and write it down: which headers, on which responses (including successful ones, not just 429), and what Retry-After contains. The IETF RateLimit header draft standardises this — consider adopting it, possibly alongside the legacy X- names for compatibility.
  2. Set the headers on every rate-limited response, not only on rejection. Clients need the remaining budget before they hit the wall.
  3. Resolve the README contradiction — either the global default is 100/min and tiers override it, or something else. State which.
  4. Document the multi-instance caveat. When the in-memory fallback is active, limits are per-process; either log a warning at startup, expose the active mode via GET /api/v1/meta (see the meta-endpoint issue), or document it in docs/.
  5. Add a RateLimit-Reset or Retry-After value on 429 that is accurate, so a well-behaved client can retry precisely rather than guessing.

Constraints

  • Headers are set in the guard, so all of this must work across every route the global guard covers — including WebSocket upgrades, which behave differently.
  • Do not leak internal configuration through headers (no pool sizes, no tier internals beyond the effective limit).
  • Keep the existing header names if any clients already rely on them; adding is safer than renaming.
  • Changing default limits is a behaviour change — note it in CHANGELOG.md.

Acceptance Criteria

  • The header contract is documented in docs/ and in the README.
  • Rate-limit headers are present on successful responses from rate-limited routes.
  • A 429 response includes an accurate Retry-After.
  • The README's rate-limit statements are consistent.
  • The multi-instance fallback behaviour is documented and discoverable.
  • Tests assert header presence and values on both success and 429 paths.
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.