Protect your server from abuse and ensure fair resource usage with rate limiting. This tutorial shows how to implement different rate limiting strategies to prevent DoS attacks and manage server load.
- How to set up basic rate limiting
- Understanding RPS (Requests Per Second) limits
- Rate limiting headers and responses
- Testing rate limiting strategies
- Best practices for production use
- ✅ RPS rate limiting - Limit requests per second per IP
- ✅ Rate limit headers - X-RateLimit-* headers for clients
- ✅ 429 responses - Proper "Too Many Requests" responses
- ✅ Interactive testing - Web interface to test limits
- ✅ Different endpoints - Show how limits apply
# Run the server
go run main.go
# Visit the interactive demo
open http://localhost:8080/This example uses a simple 5 RPS (requests per second) limit:
server, err := servex.NewServer(
servex.WithRPS(5), // Allow 5 requests per second per IP
)# Single request (should work)
curl http://localhost:8080/api/test
# Check rate limit headers
curl -I http://localhost:8080/api/testSuccessful request (within limits):
HTTP/1.1 200 OK
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 4
X-RateLimit-Reset: 1640995200
Rate limited request:
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995201
Retry-After: 1
Visit http://localhost:8080/ for an interactive demo with:
- Single Request - Test one request at a time
- Rapid Requests - Send 10 requests quickly (triggers rate limiting)
- Slow Requests - Send 10 requests slowly (stays within limits)
Servex automatically adds rate limiting headers:
| Header | Description | Example |
|---|---|---|
X-RateLimit-Limit |
Maximum requests allowed | 5 |
X-RateLimit-Remaining |
Requests remaining in current window | 3 |
X-RateLimit-Reset |
Unix timestamp when limit resets | 1640995200 |
Retry-After |
Seconds to wait before retrying (on 429) | 1 |
servex.WithRPS(10) // 10 requests per second- Best for: APIs with consistent usage patterns
- Pros: Simple, predictable
- Cons: Can be bursty
servex.WithRPM(300) // 300 requests per minute (5 RPS average)- Best for: APIs that can handle bursts
- Pros: Allows burst traffic
- Cons: Less precise control
servex.WithRPS(10), // Maximum 10 RPS
servex.WithRPM(300), // Maximum 300 RPM- Best for: Production APIs
- Pros: Handles both burst and sustained load
- Cons: More complex
API Endpoints:
- Public APIs: 100-1000 RPM
- Authenticated APIs: 1000-10000 RPM
- Internal APIs: 10000+ RPM
Web Applications:
- Login pages: 5 requests per minute (prevent brute force)
- Registration: 1 request per minute
- General pages: 100-1000 RPM
Some endpoints should typically be excluded from rate limiting:
// Health checks, metrics, etc.
servex.WithRateLimitExcludePaths("/health", "/metrics")Per-IP (default):
- Simpler implementation
- Good for public APIs
- Can affect shared IPs (offices, NAT)
Per-User:
- More accurate for authenticated APIs
- Requires user identification
- Better for SaaS applications
// Free tier: 100 RPM
servex.WithRPM(100)
// Premium tier: 1000 RPM
servex.WithRPM(1000)
// Enterprise: 10000 RPM
servex.WithRPM(10000)// Stricter for write operations
server.HandleFunc("/api/create", handler).Methods(POST)
// with lower limits
// More lenient for read operations
server.HandleFunc("/api/read", handler).Methods(GET)
// with higher limitsWhen rate limits are exceeded:
- HTTP 429 response is returned
- Retry-After header indicates wait time
- Rate limit headers show current status
- Request is rejected without processing
Clients should:
- Respect the
Retry-Afterheader - Implement exponential backoff
- Monitor rate limit headers
- Handle 429 responses gracefully
Track these metrics:
- Rate limit hit ratio - % of requests that hit limits
- 429 response rate - How often clients are rate limited
- Top rate-limited IPs - Identify potential abuse
- Rate limit effectiveness - Is it preventing issues?
🎯 Continue the tutorial: → 07-request-filtering
In the next tutorial, you'll learn how to filter and validate requests before they reach your handlers.