Rate Limiting in Go: A Guide to Request Rate Limiting

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Rate Limiting in Go: A Complete Guide to Request Rate Limiting



Rate limiting is a crucial mechanism for protection and load management in modern web applications and microservices. In the Go language (Golang), there are many approaches and libraries for implementing rate limiting, from simple to advanced. In this article, we will cover the basic concepts, popular libraries, and show code examples.



What is Rate Limiting and Why is it Needed?



Rate limiting is a technique for controlling the number of requests a client can send within a certain period of time. The main goals are:



  • Protection against DDoS attacks — preventing server overload
  • Fair resource distribution — equal access for all users
  • Resource savings — reducing infrastructure costs
  • Preventing abuse — protection against scraping and brute force


Basic Rate Limiting Algorithms



There are several classic algorithms, each with its own advantages:



  • Token Bucket — the most popular algorithm, where "tokens" accumulate at a certain rate
  • Leaky Bucket — requests are processed at a fixed rate, excess is discarded
  • Fixed Window — a simple counter of requests for a fixed time interval
  • Sliding Window — more accurate than Fixed Window, takes time boundaries into account


Popular Libraries for Rate Limiting in Go



1. Standard Library: golang.org/x/time/rate



This is an official extension from the Go team implementing the Token Bucket algorithm. It is lightweight, easy to use, and ideal for most scenarios.



package main

import ( "fmt" "net/http" "time" "golang.org/x/time/rate")

func main() { // Create a limiter: 2 requests per second, with a burst of 5 limiter := rate.NewLimiter(2, 5)

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if !limiter.Allow() { http.Error(w, "Too many requests", http.StatusTooManyRequests) return } fmt.Fprintf(w, "OK: %s", time.Now().Format(time.RFC3339)) })

http.ListenAndServe(":8080", nil)}


2. github.com/ulule/limiter



A more flexible library with support for various storage backends (Redis, Memcached, in-memory) and algorithms. Suitable for distributed systems.



import (    "github.com/gin-gonic/gin"    "github.com/ulule/limiter/v3"    "github.com/ulule/limiter/v3/drivers/store/memory")

func main() { // Configuration: 10 requests per second rate := limiter.Rate{ Period: 1 * time.Second, Limit: 10, }

store := memory.NewStore() instance := limiter.New(store, rate)

r := gin.Default() r.Use(func(c *gin.Context) { key := c.ClientIP() context, err := instance.Get(c.Request.Context(), key) if err != nil { c.AbortWithStatusJSON(500, gin.H{"error": "Internal error"}) return } if context.Reached { c.AbortWithStatusJSON(429, gin.H{"error": "Too many requests"}) return } c.Next() })

r.Run(":8080")}


3. github.com/juju/ratelimit



A simple and reliable library from Canonical, based on the Token Bucket algorithm. It features a minimalist API.



import (    "github.com/juju/ratelimit"    "time")

func main() { // Create a bucket: 100 tokens, refill 10 tokens per second bucket :=

Recommendations