Skip to content

Rate Limiting Guide ​

HTTPX provides token-bucket rate limiting via httpx.RateLimiter to protect servers from abuse, brute-force attempts, and denial of service attacks.

Token Bucket Algorithm ​

zig
const std = @import("std");
const httpx = @import("httpx");

fn limitedHandler(ctx: *httpx.Context) anyerror!httpx.Response {
    return ctx.renderJson(.{ .status = "ok", .data = "sensitive information" });
}

pub fn main() !void {
    var gpa: std.heap.DebugAllocator(.{}) = .init;
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();
    const io = std.Io.Threaded.global_single_threaded.io();

    var server = try httpx.Server.init(allocator, io, .{ .port = 8080 });
    defer server.deinit();

    // 10 requests per 60s window, burst up to 10.
    var limiter = httpx.RateLimiter.init(allocator, 10, 60_000);
    defer limiter.deinit();

    try server.get("/api/data", limitedHandler);

    server.run();
}

Gate per request with check(key, nowMs) (remaining quota, or null when limited) or checkDetailed for full RateLimitResult metadata (allowed, remaining, resetSeconds, retryAfterSeconds). Build keys by dimension (RateLimitDimension: .global, .clientIp, .userId, .apiKey, .route, .userAndRoute, .ipAndRoute, .custom).

Configure windows with RateLimitPolicy (.limit, .windowMs, .burst, .ttlMs) via init(allocator, .{ .policy, .maxEntries }).

Rate Limiting Headers ​

RateLimitResult.toResponse(allocator) renders a 429 response with standard headers:

  • X-RateLimit-Limit: Maximum bucket capacity.
  • X-RateLimit-Remaining: Tokens remaining in the current window.
  • X-RateLimit-Reset: Seconds until bucket is fully replenished.
  • Retry-After: Seconds to wait before retrying (on 429 responses).

Released under the MIT License.