Project 5: Rate Limiter Library
A production-grade rate limiting library implementing multiple algorithms (token bucket, sliding window, leaky bucket) with a clean API, suitable for use in HTTP middleware.
Quick Reference
| Attribute | Value |
|---|---|
| Primary Language | Go |
| Alternative Languages | Rust, Java, C++ |
| Difficulty | Level 3: Advanced |
| Time Estimate | 1-2 weeks |
| Knowledge Area | Algorithms, Time Management, API Design |
| Tooling | None (from scratch) |
| Prerequisites | Completed Projects 1-4. Strong understanding of concurrency. Familiarity with rate limiting concepts. |
What You Will Build
A production-grade rate limiting library implementing multiple algorithms (token bucket, sliding window, leaky bucket) with a clean API, suitable for use in HTTP middleware.
Why It Matters
This project builds core skills that appear repeatedly in real-world systems and tooling.
Core Challenges
- Implementing rate limiting algorithms → maps to time package and algorithm design
- Making it thread-safe → maps to sync.Mutex and atomic operations
- Designing a clean API → maps to interface design and Go idioms
- Testing time-dependent code → maps to test design and mocking
Key Concepts
- Token bucket algorithm: System Design resources
- Time handling: “The Go Programming Language” Ch. 6 - Donovan & Kernighan
- sync/atomic: “Concurrency in Go” Ch. 3 - Katherine Cox-Buday
- Interface design: “100 Go Mistakes” Ch. 2 - Teiva Harsanyi
Real-World Outcome
// Create a rate limiter: 100 requests per second, burst of 10
limiter := ratelimit.NewTokenBucket(100, 10)
// Use in HTTP middleware
func RateLimitMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
clientIP := r.RemoteAddr
if !limiter.Allow(clientIP) {
http.Error(w, "Rate limit exceeded", http.StatusTooManyRequests)
return
}
next.ServeHTTP(w, r)
})
}
// Different algorithms available
tokenBucket := ratelimit.NewTokenBucket(rate, burst)
slidingWindow := ratelimit.NewSlidingWindow(rate, windowSize)
leakyBucket := ratelimit.NewLeakyBucket(rate)
// Check current state
info := limiter.Status("client-123")
fmt.Printf("Remaining: %d, Reset in: %v\n", info.Remaining, info.ResetIn)
Implementation Guide
- Reproduce the simplest happy-path scenario.
- Build the smallest working version of the core feature.
- Add input validation and error handling.
- Add instrumentation/logging to confirm behavior.
- Refactor into clean modules with tests.
Milestones
- Milestone 1: Minimal working program that runs end-to-end.
- Milestone 2: Correct outputs for typical inputs.
- Milestone 3: Robust handling of edge cases.
- Milestone 4: Clean structure and documented usage.
Validation Checklist
- Output matches the real-world outcome example
- Handles invalid inputs safely
- Provides clear errors and exit codes
- Repeatable results across runs
References
- Main guide:
LEARN_GO_DEEP_DIVE.md - “100 Go Mistakes and How to Avoid Them” by Teiva Harsanyi