feat(security): add per-IP rate limiting with Redis + in-memory support#568
Merged
lakhansamani merged 11 commits intomainfrom Apr 4, 2026
Merged
feat(security): add per-IP rate limiting with Redis + in-memory support#568lakhansamani merged 11 commits intomainfrom
lakhansamani merged 11 commits intomainfrom
Conversation
Covers multi-replica aware rate limiting with Redis sliding window (distributed) and x/time/rate in-memory fallback, CLI configurability via --rate-limit-rps and --rate-limit-burst, and exempt path list.
7-task plan covering config/CLI flags, rate_limit provider package (in-memory + Redis), middleware rewrite, wiring, and integration tests.
Introduces the rate_limit package with a Provider interface and an in-memory token-bucket implementation backed by golang.org/x/time/rate. Includes a Redis stub that will be replaced in Task 3.
- Remove applyFlagDefaults override so --rate-limit-rps=0 disables rate limiting - Add defer rateLimitProvider.Close() for graceful shutdown - Simplify Redis Lua script: remove redundant GET, use INCR-only pattern - Add compile-time interface guards for inMemoryProvider and redisProvider - Document benign lastSeen data race in entry struct
Add critical rule #6 to CLAUDE.md: always use feature branches, push to branch, create merge request. Main must stay deployable.
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
golang.org/x/time/rate) fallback for single-instance--rate-limit-rps(default: 10) and--rate-limit-burst(default: 20)--rate-limit-rps=0to disable429 Too Many RequestswithRetry-After: 1header and OAuth2 error formatChanges
internal/rate_limit/— New package withProviderinterface,inMemoryProvider(token bucket viax/time/rate+sync.Map), andredisProvider(atomic Lua sliding-window script)internal/config/config.go— AddedRateLimitRPSandRateLimitBurstfieldscmd/root.go— Added--rate-limit-rpsand--rate-limit-burstCLI flags, wired provider (reuses Redis connection from memory store when available)internal/http_handlers/rate_limit.go— Rewrote middleware: calls provider, skips 10 exempt paths (health, metrics, OIDC discovery, static assets)internal/http_handlers/provider.go— AddedRateLimitProviderto Dependenciesinternal/server/http_routes.go— Placed middleware after CORS, before ClientCheckinternal/memory_store/redis/provider.go— AddedEvalto RedisClient interface, exposedClient()methodCLAUDE.md— Added critical rule: never commit to mainExempt paths (not rate limited)
/,/health,/healthz,/readyz,/metrics,/playground,/.well-known/openid-configuration,/.well-known/jwks.json,/app/*,/dashboard/*Security considerations
Retry-Afterheader per RFC 6585 for well-behaved clients/graphql,/oauth/token,/oauth_login,/verify_email, etc.Test plan
TestRateLimitMiddleware/should_allow_requests_within_limitTestRateLimitMiddleware/should_reject_requests_over_limit(burst exhaustion → 429)TestRateLimitMiddleware/should_not_rate_limit_exempt_paths(health, metrics, OIDC)TestRateLimitMiddleware/should_isolate_rate_limits_per_ipTestRateLimitMiddleware/should_return_correct_error_format(OAuth2 error + Retry-After)TestInMemoryRateLimitProvider/should_allow_up_to_burstTestInMemoryRateLimitProvider/should_deny_after_burstTEST_DBS=sqlitego build ./...passes