Repository navigation
Replace in-process Map-based rate limiter with a Redis ZSET sliding-window #212
Description
Problem Statement. createRateLimiter() in app/backend/src/common/security/security.module.ts
uses a process-locale Map<string, {count, resetTimeMs}> as its store. At scale, this
(a) wastes memory proportional to unique client IPs, (b) silently loses the limit counter when
the process restarts (an attacker simply widens their budget across restarts), (c) does not
share state across the many replicas one would deploy behind a load balancer.
Why it matters. Rate limiting is one of the cheapest, broadest defenses. A loss-of-state
or per-replica division of the limit is the difference between effective DoS mitigation and
incidental throttling.
Technical Context. The repo already imports both @liaoliaots/nestjs-redis and
@nestjs/throttler. The throttler module is configured with a global 20 req/min limit in
app.module.ts. The current createRateLimiter is registered as an Express middleware via
app.use(createRateLimiter(cs)) in main.ts. The store needs to be migrated.
Expected Outcome. A sliding-window limiter using a Redis sorted set, with all current
behaviour preserved (headers, exempt paths, isVerificationPath special case) and configurable
window/limit via env.
Acceptance Criteria.
- New
RedisSlidingWindowRateLimitermiddleware with the same interface
((req, res, next) => void). - Configurable via
RATE_LIMIT_WINDOW_MSandRATE_LIMIT_LIMITenvs. - A new e2e test asserts: 100 hits in 1 s => 80+ return 429, headers include
RateLimit-Limit,RateLimit-Remaining,RateLimit-Reset,Retry-After. - A redis-down test (use
ioredis-mock) asserts the limiter fails open with a WARN log,
not 500.
Implementation Notes. Replace the Map store with a ZADD/ZCOUNT/ZREMRANGEBYSCORE
per key; reuse the req.ips[0] fallback for the key. Use MULTI to keep header reads
consistent.
Files or modules likely to be affected. src/common/security/security.module.ts,
src/common/guards/adaptive-rate-limit.guard.ts, app/backend/test/security.e2e-spec.ts,
app.module.ts (registration order).
Dependencies. None (but mutually exclusive with the throttler guard in #46).
Difficulty. Hard
Estimated effort. M
Backlog item #4 from `docs/maintainer-issue-backlog.md.
Activity
AugistineCreates commentedon Jul 15, 2026
Please assign this issue to me my eta is 4 hours
grantfox-oss commentedon Jul 15, 2026
🦊 GrantFox — @AugistineCreates has been assigned to this issue as part of the Official Campaign | FWC26 campaign!
Next steps:
Closes #212)Good luck! Track your progress on GrantFox.
grantfox-oss commentedon Jul 19, 2026
🎉 This issue has been marked as completed on GrantFox as part of the Official Campaign | FWC26 campaign!
@AugistineCreates's PR #343 was approved and merged by @kilodesodiq-arch.
🏆 @AugistineCreates: You earned 45 FoxPoints for this contribution! Your current tier: Specialist (3,124 total points). Track your full progress on GrantFox.
👏 Great work, @AugistineCreates! Keep contributing to ChainForgee.