DEV Community

Cover image for Building Better APIs with ThrottleX: Rate Limiting Done Right
Neel Patel
Neel Patel

Posted on

Building Better APIs with ThrottleX: Rate Limiting Done Right

LINKS: https://github.com/neelp03/throttlex

Hey Dev community! 👋 I'm pretty new to the open-source world, and I'd love any advice you might have.

If you've ever built an API that needed to manage traffic control, you know that rate limiting is crucial for keeping things fair and efficient. Today, I'm excited to introduce you to my open-source project: ThrottleX — a powerful, flexible, and easy-to-use rate limiter for your APIs! 🚀

What's ThrottleX?

ThrottleX is a distributed rate-limiting library for Go that helps you ensure fair use of your API resources, even under heavy load. Whether you're facing a surge of requests from a single user or want to prevent misuse, ThrottleX has you covered with multiple rate-limiting strategies.

Current Features 💡

ThrottleX currently supports three core rate-limiting policies:

  1. Fixed Window Rate Limiting

    • Imagine you're running a small coffee shop, and you only have a certain number of espresso shots available per minute. Fixed Window limits requests to a set number during a fixed time interval — simple, effective, and great for managing bursts of API traffic.
  2. Sliding Window Rate Limiting

    • Sliding Window works similarly but acts like a moving average for requests. Instead of resetting entirely, it provides more granular control over requests to avoid sudden spikes. It's like distributing your espresso shots more evenly throughout each minute to maintain steady service. ☕
  3. Token Bucket Rate Limiting

    • This policy lets you accumulate tokens over time and spend them as needed. It's flexible, allowing for bursts of activity as long as there are enough tokens available. Think of it as someone buying multiple coffees if they've saved up enough loyalty tokens! ☕🎟️

What's Next? Future Roadmap

We're not done yet! Here's what we're working on for ThrottleX to make it even more versatile:

  • Prioritized Rate Limiting: Different users, different priorities! Soon we'll be able to prioritize requests for specific users or services.
  • Request Token Policy: Allow users to present specific tokens to increase their rate limit.
  • Exponential Backoff Rate Limiting: Gradually increase wait times for clients who keep hitting the rate limits.
  • Geographic Rate Limiting: Set different rate limits based on geographic regions. 🌍
  • Hierarchical Rate Limiting: Apply rate limits across users/groups in a hierarchical structure.
  • Dynamic Rate Limiting: Adjust rate limits dynamically based on server load. 🌡️
  • Request Quota Policies (Fixed/Rolling Quota): Set different quotas for users or groups over extended periods.
  • Concurrency Limit: Limit the number of simultaneous requests.
  • Leaky Bucket Algorithm: Similar to the token bucket but enforces a steady flow rate, preventing sudden bursts.

We want ThrottleX to be the Swiss Army Knife of rate limiting. 🛠️


How to Use ThrottleX

Getting started with ThrottleX is simple! Add it to your Go project, and you're ready to go. Here's a quick example of using one of the policies:

package main

import (
    "github.com/neelp03/throttlex/ratelimiter"
    "github.com/neelp03/throttlex/store"
    "time"
    "fmt"
)

func main() {
    // Initialize an in-memory store and a fixed window rate limiter
    memStore := store.NewMemoryStore()
    limiter, err := ratelimiter.NewFixedWindowLimiter(memStore, 10, time.Second*60)
    if err != nil {
        fmt.Println("Failed to create limiter:", err)
        return
    }

    // Simulate requests
    key := "user1"
    for i := 0; i < 12; i++ {
        allowed, err := limiter.Allow(key)
        if err != nil {
            fmt.Println("Error:", err)
            continue
        }
        if allowed {
            fmt.Printf("Request %d allowed\n", i+1)
        } else {
            fmt.Printf("Request %d blocked\n", i+1)
        }
    }

    // Simulate requests from multiple clients (e.g., 25 clients)
    clients := 25
    for i := 0; i < clients; i++ {
        key := fmt.Sprintf("client%d", i+1)
        for j := 0; j < 12; j++ {
            allowed, err := limiter.Allow(key)
            if err != nil {
                fmt.Printf("Client %d - Error: %v\n", i+1, err)
                continue
            }
            if allowed {
                fmt.Printf("Client %d - Request %d allowed\n", i+1, j+1)
            } else {
                fmt.Printf("Client %d - Request %d blocked\n", i+1, j+1)
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

In the example above, we use Fixed Window Limiting to restrict user1 to 10 requests per minute. When the 11th and 12th requests are made, they are blocked, ensuring fair usage. We also demonstrate how to simulate 25 clients making requests, each independently rate-limited.

Redis Example for Distributed Environments

ThrottleX also supports Redis as a storage backend, ideal for distributed environments where you need to enforce rate limits across multiple servers:

package main

import (
    "github.com/go-redis/redis/v8"
    "github.com/neelp03/throttlex/ratelimiter"
    "github.com/neelp03/throttlex/store"
    "time"
    "fmt"
    "context"
)

func main() {
    // Set up Redis client
    client := redis.NewClient(&redis.Options{
        Addr: "localhost:6379",
    })
    err := client.Ping(context.Background()).Err()
    if err != nil {
        fmt.Println("Failed to connect to Redis:", err)
        return
    }

    // Initialize a Redis store and a fixed window rate limiter
    redisStore := store.NewRedisStore(client)
    limiter, err := ratelimiter.NewFixedWindowLimiter(redisStore, 10, time.Second*60)
    if err != nil {
        fmt.Println("Failed to create limiter:", err)
        return
    }

    // Simulate requests from multiple clients (e.g., 25 clients)
    clients := 25
    for i := 0; i < clients; i++ {
        key := fmt.Sprintf("client%d", i+1)
        for j := 0; j < 12; j++ {
            allowed, err := limiter.Allow(key)
            if err != nil {
                fmt.Printf("Client %d - Error: %v\n", i+1, err)
                continue
            }
            if allowed {
                fmt.Printf("Client %d - Request %d allowed\n", i+1, j+1)
            } else {
                fmt.Printf("Client %d - Request %d blocked\n", i+1, j+1)
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

This example demonstrates how to use Redis to enforce Fixed Window Limiting across multiple clients. Redis enables rate limit management in a distributed setup, making ThrottleX a great choice for scaling applications.


Why ThrottleX? 🤔

While there are many rate limiters available, ThrottleX is designed to be lightweight, highly configurable, and adaptable for distributed environments. With support for both in-memory and Redis storage, ThrottleX gives you the flexibility you need, whether you're working on small projects or deploying enterprise-grade solutions. ✨

Join the ThrottleX Journey 🚀

I love the open-source community and would love for you to be part of this journey. ThrottleX is still evolving, and if you have ideas, feature requests, or want to contribute, please do! Let's make rate limiting easier and more enjoyable for everyone.

The GitHub repository is here: ThrottleX GitHub Repo

Drop by, give it a star ⭐ if you like it, and join the conversation!

Final Thoughts

Building APIs is challenging, and ensuring they run smoothly while providing fair access is even more challenging. ThrottleX is my attempt at making that easier for developers everywhere.

I can't wait to hear your thoughts and see what we can build together. Let's keep making the web better, one request at a time!

Happy coding, everyone!


Diagrams for Better Understanding

Here are some diagrams to help visualize how ThrottleX works:

This flowchart represents how a request passes through ThrottleX, which either allows or blocks the request based on the configured rate limiting policy.

This flowchart represents how a request passes through ThrottleX, which either allows or blocks the request based on the configured rate limiting policy.

This diagram shows the different rate-limiting policies currently supported by ThrottleX, all contributing to its core functionality.

This diagram shows the different rate-limiting policies currently supported by ThrottleX, all contributing to its core functionality.

Top comments (2)

Collapse
 
0vortex profile image
TED Vortex (Teodor Eugen Duțulescu)

this looks really good but please change the name to something unique so users can actually find the tool - example: 1. you hear about throttlex go but did not read this article with the direct link; 2. you google "throttlex" and sidetrack; 3. you google "throttlex github" ... and sidetrack

Collapse
 
neelp03 profile image
Neel Patel

Thanks for the feedback, and I really appreciate you pointing that out! I totally get what you're saying about discoverability and having a unique name can definitely help people find the project more easily. I'll look into renaming it to something more distinct so users can track it down without getting sidetracked on Google.

If you have any name suggestions, feel free to drop them! I’m always open to ideas. 😊