Integration Recipes: Filter Ordering, Gateways, and User Tiers
This guide covers common integration points: ordering the rate limiter filter, running behind a gateway, and deriving user tiers safely.
Prerequisites
- A Spring Boot service using the rate limiter filter
- Clear understanding of your gateway or proxy layer
- A trusted source of user tier data (JWT, API key, or user service)
Filter ordering in Spring
The rate limiter runs as a OncePerRequestFilter. It should execute early enough to protect downstream components, but after any filter that establishes authentication context if your tier logic depends on it.
Recommended order:
- Authentication (JWT, API key)
- Tier resolution (derive user tier from claims or database)
- Rate limiter filter
- Business controllers
If the rate limiter runs before authentication, all requests will default to a base tier because tier data is not yet available. If it runs too late, expensive downstream work will occur before the limit is enforced.
Running behind a gateway
When the app is behind a gateway (nginx, Envoy, API Gateway, or an ingress controller), make sure the gateway forwards the client IP and does not overwrite it. The rate limiter uses proxy headers only when the gateway IP is in the trusted proxy list.
Key configuration points:
- Ensure the gateway adds
X-Forwarded-Forand preserves the chain. - Add the gateway IP or CIDR range to
rate-limit.security.trusted-proxies. - Use TLS from the gateway to the app to avoid header tampering on internal networks.
If you skip the trusted proxy configuration, all traffic will appear to come from the gateway IP and you will see global throttling rather than per-client limits.
Deriving user tiers safely
User tiers should come from trusted auth context, not from client input. The configuration endpoint accepts a userTier field for overrides, but that is metadata attached to the override, not a signal from runtime traffic.
Practical approaches:
- JWT claim: derive tier from
planortierclaim set by your auth service. - API key lookup: resolve the key to a tier in your database.
- Service-to-service header: use a signed header from a gateway you control.
Once the tier is resolved, add it to the request context so the rate limiter can choose the correct configuration branch.
Per-endpoint and method-based limits
The configuration model supports method fields in the override documents. Use this when the same path should have different limits for GET versus POST.
Example override for POST-heavy endpoints:
{
"ip": "192.168.1.100",
"endpoint": "/api/orders",
"userTier": "premium",
"method": "POST",
"algorithm": "TOKEN_BUCKET",
"parameters": {
"capacity": 20,
"refillRate": 5
}
}If you do not set method, the override applies to all methods for that endpoint. Use method-specific overrides sparingly to keep configuration complexity manageable.
What to verify
- Auth filters run before rate limiting when tier depends on authentication.
- Client IP is resolved correctly when traffic passes through a gateway.
- The derived user tier matches the expected configuration branch in
rate-limit.endpoints.