Non-atomic decrement under concurrent requests. Two requests for the same IP both read `bucket.tokens = 4`, both subtract 2, both check `< 0`, both write 2 — both pass. Node's event loop serializes single-process JS, but the same Map over cluster workers or behind a load balancer will lose decrements. Add a brief comment noting `single-process only — move to Redis Lua before scaling out`, or use a lock-free atomic here: read with `bucket.tokens`, compute `next = bucket.tokens - cost`, write with a CAS loop until the read matches.
src/middleware/rateLimit.js:23
'cost' shadows the request middleware convention used elsewhere in src/. Either inline the literal `2` for now, or rename to `costTokens` so future endpoints with parameterised cost don't collide. One-line nit — fine to skip.
src/middleware/rateLimit.js:23
Want this on every PR?
Install SiftPulse on GitHub
First review posts within 60 seconds. 14-day free trial.
Floor swallows the decrement. `bucket.tokens = bucket.tokens - cost` already pushed the value negative by the time you check `< 0` and 429 the caller, so on the NEXT request that IP starts from a negative balance and has to wait through the refill before being allowed — but you only re-check `< 0` after the next decrement, so the IP will be silently throttled for up to `cost / REFILL_PER_SEC = 0.2s` longer than documented. Subtract, then floor: `bucket.tokens = Math.max(0, bucket.tokens - cost); if (bucket.tokens === 0) return res.status(429)…` — that way the bucket value stays non-negative AND the 429 is consistent.
src/middleware/rateLimit.js:22