# How to Implement Rate Limiting in Gorig's HTTP Server: Using the Built-In Debounce Middleware

> Learn how to implement rate limiting in Gorig's HTTP server using the built-in Debounce middleware. Throttle requests efficiently per IP or user with this high-performance solution.

- Repository: [Jom/gorig](https://github.com/jom-io/gorig)
- Tags: how-to-guide
- Published: 2026-03-05

---

**Gorig implements rate limiting through a built-in Debounce middleware in the `httpx` package that throttles requests per IP or authenticated user using a high-performance sharded in-memory map with a default 200ms window.**

Gorig provides a production-ready solution for request throttling without requiring external dependencies. The framework automatically configures rate limiting during server startup using the **Debounce** middleware found in [`httpx/mid.debounce.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.debounce.go), which integrates directly with the Gin engine to protect your endpoints from rapid-fire requests.

## Understanding Gorig's Debounce Middleware

The **Debounce** middleware acts as a request deduplication layer that prevents clients from flooding your server with identical calls within a configurable time window. According to the Gorig source code, this middleware constructs a unique key using either `<path>:id:<userId>` for authenticated users or `<path>:ip:<clientIP>` for anonymous clients, storing timestamps in a specialized `ShardedRequestMap` structure.

The implementation resides in [[`httpx/mid.debounce.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.debounce.go)](https://github.com/jom-io/gorig/blob/master/httpx/mid.debounce.go) and automatically attaches to the global Gin engine in [[`httpx/serv.go`](https://github.com/jom-io/gorig/blob/main/httpx/serv.go)](https://github.com/jom-io/gorig/blob/master/httpx/serv.go#L78-L83) during server initialization (lines 78-83):

```go
gEngine.Use(Debounce(200 * time.Millisecond))

```

This configuration applies a **200-millisecond** throttle window by default, meaning subsequent identical requests from the same client within that timeframe receive an immediate **429 Too Many Requests** response via `response.ErrorTooManyRequests`.

## How Rate Limiting Works Under the Hood

When an HTTP request enters the system, the middleware executes a multi-step validation process:

1. **Whitelist Check**: The middleware first verifies if the requested path exists in the internal `whiteList` slice populated via `DebouceAw()`. Whitelisted routes bypass all throttling logic.

2. **Client Identification**: The system extracts a unique identifier using `GetTokenByCtx` (defined in [`httpx/mid.sign.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.sign.go), lines 108-119) to retrieve the authenticated user ID. If authentication is absent, the client's IP address serves as the fallback identifier.

3. **Sharded Map Lookup**: The unique key queries the `ShardedRequestMap`, which distributes entries across **32 shards**—each protected by its own `RWMutex`. This architecture minimizes lock contention and enables near lock-free lookups for high-throughput scenarios.

4. **Expiration Logic**: If the key exists and the elapsed time remains below the configured duration, the middleware aborts the request chain with HTTP 429. Otherwise, it records the current timestamp and permits the request to proceed.

5. **Memory Management**: A background routine automatically clears individual shards when they exceed approximately **2 MiB**, preventing unbounded memory growth in long-running services.

## Implementation Examples

### Default Configuration (200ms)

No additional code is required to enable basic rate limiting. The framework automatically registers the middleware during server boot in [`httpx/serv.go`](https://github.com/jom-io/gorig/blob/main/httpx/serv.go):

```go
// Server starts with default 200ms debounce automatically
// All routes protected except those explicitly whitelisted

```

### Custom Debounce Intervals

Override the default window by re-registering the middleware with a custom `time.Duration`. This approach replaces the automatic configuration with your specified interval:

```go
import "github.com/jom-io/gorig/httpx"
import "time"

func init() {
    // Extend throttle window to 500ms for high-latency operations
    httpx.RegisterRouterMid(func(g *gin.RouterGroup, mids ...gin.HandlerFunc) *gin.RouterGroup {
        g.Use(httpx.Debounce(500 * time.Millisecond))
        return g
    })
}

```

### Whitelisting Specific Routes

Exclude health checks, metrics endpoints, or public APIs from rate limiting using the `DebouceAw` function (note the function naming as implemented in the source):

```go
import "github.com/jom-io/gorig/httpx"

func init() {
    // These paths bypass the sharded request map entirely
    httpx.DebouceAw("/health", "/metrics", "/api/public/status")
}

```

### Disabling Rate Limiting for Testing

Integration tests often require rapid sequential requests. Globally disable the middleware using `DebounceDisable()`, which sets the internal `enable` flag to `false`:

```go
import "github.com/jom-io/gorig/httpx"
import "testing"

func TestMain(m *testing.M) {
    // Disable throttle for entire test suite
    httpx.DebounceDisable()
    m.Run()
}

```

### Custom Router Integration

For applications using manually instantiated Gin engines rather than the global server, apply the middleware directly:

```go
router := gin.New()
// Apply 300ms debounce to this specific router instance
router.Use(httpx.Debounce(300 * time.Millisecond))
router.GET("/api/data", func(c *gin.Context) {
    // Handler logic executes only if request passes throttle check
})

```

## Key Source Files and Architecture

Understanding the following files enables advanced customization of Gorig's rate limiting behavior:

- **[`httpx/mid.debounce.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.debounce.go)**: Contains the complete Debounce implementation including the `ShardedRequestMap` struct, `Debounce(duration)` constructor, `DebouceAw()` whitelist manager, and `DebounceDisable()` global toggle.

- **[`httpx/serv.go`](https://github.com/jom-io/gorig/blob/main/httpx/serv.go)**: Server bootstrap code that registers the default middleware (lines 78-83). Modify this file to change framework-wide defaults.

- **[`httpx/mid.sign.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.sign.go)**: Defines `GetTokenByCtx` (lines 108-119), the helper function extracting user IDs for authenticated rate limiting.

- **[`apix/response/response.go`](https://github.com/jom-io/gorig/blob/main/apix/response/response.go)**: Implements `ErrorTooManyRequests`, the HTTP 429 response generator used when throttling triggers.

## Summary

- Gorig's rate limiting relies on the **Debounce** middleware located in [`httpx/mid.debounce.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.debounce.go), utilizing a sharded in-memory map for high-performance request deduplication.
- The default configuration applies a **200ms** throttle window to all routes, automatically registered during server startup in [`httpx/serv.go`](https://github.com/jom-io/gorig/blob/main/httpx/serv.go).
- **Client identification** prioritizes authenticated user IDs via `GetTokenByCtx`, falling back to IP addresses for unauthenticated requests.
- The **sharded architecture** (32 shards with independent RWMutexes) minimizes lock contention, while automatic cleanup prevents memory leaks at scale.
- **Whitelist management** via `DebouceAw()` and global disable via `DebounceDisable()` provide flexible control for health checks, metrics, and testing environments.

## Frequently Asked Questions

### What is the default rate limit window in Gorig?

The default throttle duration is **200 milliseconds**, configured in [`httpx/serv.go`](https://github.com/jom-io/gorig/blob/main/httpx/serv.go) during engine initialization. This value strikes a balance between user experience and server protection for most web applications.

### How does Gorig differentiate between authenticated and unauthenticated users for rate limiting?

The middleware attempts to extract a user ID first by calling `GetTokenByCtx` from the request context (as defined in [`httpx/mid.sign.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.sign.go)). If no authentication token exists, it falls back to the client's IP address, creating keys in the format `<path>:ip:<clientIP>` rather than `<path>:id:<userId>`.

### Can I disable rate limiting for specific API endpoints while keeping it active for others?

Yes. Use the `DebouceAw()` function to append specific paths to the internal `whiteList` slice. Routes matching these patterns bypass the `ShardedRequestMap` lookup entirely and execute without throttle checks.

### What HTTP status code does Gorig return when rate limiting triggers?

When a request exceeds the configured rate limit, Gorig responds with **HTTP 429 Too Many Requests** using the `ErrorTooManyRequests` function from [`apix/response/response.go`](https://github.com/jom-io/gorig/blob/main/apix/response/response.go). This standard status code signals clients to implement exponential backoff strategies.