Building a Simple Rate Limiter Middleware in Go using Gin
Tags: go, middleware, rate, limiter
Published: 2023-11-08 01:23:39

---
title: Building a Simple Rate Limiter Middleware in Go using Gin
published: true
date: 2023-11-06 15:52:44 UTC
tags: #go #middleware #rate #limiter
canonical_url: https://carlosmv.hashnode.dev/building-a-simple-rate-limiter-middleware-in-go-using-gin
---

In this article, we are going to build a Rate Limiter middleware for a Gin server.

We will build a very simple rate limiter, one that stops accepting requests when these exceed the limit in a certain time frame. We Will not create a rate limiter that keeps track of the IP Addresses and stops them from making too many requests.

### Rate Limiter

According to [this article](https://www.cloudflare.com/learning/bots/what-is-rate-limiting/), published by CloudFlare, a rate limiter is a strategy for limiting network traffic. It puts a cap on how often someone can repeat an action within a certain timeframe for instance, trying to log in to an account. Rate limiting can help stop certain kinds of malicious bot activity. It can also reduce strain on web servers.

Rate limiting is often employed to stop bad bots from negatively impacting a website or application. Bot attacks that rate limiting can help mitigate include Brute force attacks, DoS and DDoS attacks and Web scraping.

Rate limiting also protects against API overuse, which is not necessarily malicious or due to bot activity, but is important to prevent nonetheless.

### Requirements

- Go installed

### Rate Limiter Algorithms

- **Fixed window algorithm:** This algorithm maintains a counter of the number of requests made within a fixed time window, such as one minute. If the counter exceeds the rate limit, subsequent requests are rejected.

- **Sliding window algorithm:** This algorithm is similar to the fixed window algorithm, but the time window slides forward as new requests are received. This means that requests that were made earlier in the window may still be counted against the rate limit, even if they are no longer within the current window.

- **Leaky bucket algorithm:** This algorithm maintains a bucket that fills up at a constant rate. When a request is received, it is allowed to pass through the bucket if there is space available. If the bucket is full, the request is rejected.

- **Token bucket algorithm:** This algorithm is similar to the leaky bucket algorithm, but instead of a bucket, it maintains a counter of tokens. Tokens are added to the counter at a constant rate, and requests are allowed to pass through if there is at least one token available. If the counter is empty, requests are rejected.

### Simple Rate Limiter

We created a new Go project, RateLimiter. And installed Gin.

```
$ go get -u github.com/gin-gonic/gin

```

For this rate limiter we are going to use the rate package. Which implements the token bucket algorithm.

And in the `main.go` file, we start creating a handler that will be used to limit the number of requests made to the server.

**main.go**

```go
package main

import (

    "github.com/gin-gonic/gin"

    "golang.org/x/time/rate"
)

func RateLimiter() gin.HandlerFunc {
    limiter := rate.NewLimiter(1, 4)
    return func(c *gin.Context) {

        if limiter.Allow() {
            c.Next()
        } else {
            c.JSON(http.StatusTooManyRequests, gin.H{
                "message": "Limite exceed",
            })
        }

    }

```

This is the `RateLimiter()` function, we create a NewLimiter instance that allows up to 4 requests per second. According to the [documentation](https://pkg.go.dev/golang.org/x/time/rate#pkg-functions), the NewLimiter function returns a new Limiter, `func NewLimiter(r Limit, b int) *Limiter` and a Limiter controls how frequently events are allowed to happen. It implements a "token bucket" of size `b`, initially full and refilled at the rate of `r` tokens per second.

The zero value is a valid Limiter, but it will reject all events. Use NewLimiter to create non-zero Limiters.

The `Allow()` method of the rate limiter returns a boolean value indicating whether the request is allowed. If the request is allowed, the `Next()` method of the `gin.Context` object is called to continue processing the request. Otherwise, the `JSON()` method of the `gin.Context` object is called to send a response with the status code `429` (Too Many Requests).

```go
func main() {
    r := gin.Default()
    r.Use(RateLimiter())
    r.GET("/", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{
            "message": "pong",
        })
    })
    r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}

```

In the `main()` function, we create a Gin instance and use the `Use()` function to register the `RateLimiter()` middleware.

The `RateLimiter()` handler is called every time a request is made to the server.

In our command line, we run this file using `go run main.go` command.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1688866852782/649b3cc0-c74a-4739-a0b0-9642a97eeff2.png)

To test this rate limiter, we created another project, `TestLimiter`. And use the following code in its `main.go` file.

```go
package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

func main() {
    c := http.Client{Timeout: time.Duration(1) * time.Second}
    limit := 20

    for i := 1; i < limite; i++ {
        resp, err := c.Get("http://localhost:8080/")
        if err != nil {
            fmt.Printf("Error %s", err)
            fmt.Println("Count is: ", i)
            return
        }
        defer resp.Body.Close()
        body, err := ioutil.ReadAll(resp.Body)
        fmt.Printf("Body : %s", body)
    }
}

```

In this file, we define the `c` variable, which is a `http.Client` object that is used to make HTTP requests. The `limit` variable is an integer variable that specifies the number of times the `Get()` method will be called.

Then we created a loop that iterates `limit` times. In each iteration of the loop, the code makes a `Get()` request to the URL [`http://localhost:8080/`](http://localhost:8080/). The `Get()` method returns an `*http.Response` object, which contains the response from the server.

The code then checks the `err` variable to see if there was an error in making the request. If there is an error, the code prints the error message and the current value of the `i` variable. Otherwise, the code reads the body of the response and prints it to the console.

We run this file, using `go run main.go` in another terminal.

The Rate Limiter terminal should show these messages:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1688866983625/86117957-a105-45d2-bdc7-81160945aef3.png)

And the `TestLimiter` terminal should show these messages:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1688867028465/460f53c9-79b7-483c-a699-da66484bb2d5.png)

### Conclusion

In this article, we built a rate limiter for a Gin server. Building a rate limiter for your Gin server is an important step in protecting your application from abuse. By limiting the number of requests that can be made to your server, you can help improve the performance and reliability of your application for all users.

The source code is [here](https://github.com/carlosm27/rateLimiter).

Thank you for taking the time to read this article.

If you have any recommendations about other packages, architectures, how to improve my code, my English, or anything; please leave a comment or contact me through [**Twitter**](https://twitter.com/Carlos_marcv), or [**LinkedIn**](https://www.linkedin.com/in/carlos-marcano-a2135a134/).

### Resources

[What is rate limiting](https://www.cloudflare.com/learning/bots/what-is-rate-limiting/)

[What Is a Rate Limiter?](https://builtin.com/software-engineering-perspectives/rate-limiter)

[Rate limiting your Go application](https://blog.logrocket.com/rate-limiting-go-application/)

[Rate package documentation](https://pkg.go.dev/golang.org/x/time/rate)