DevOpsil

Distributed Rate Limiting API

Distributed Rate Limiting checks and enforces per-user, per-IP, or per-tenant request quotas across your entire fleet — with three algorithms, atomic Redis-backed counters, and sub-millisecond response.

Quick start →View DocsPOST https://devopsil.com/api/v1/ratelimit/increment

What is it?

Distributed Rate Limiting checks and enforces per-user, per-IP, or per-tenant request quotas across your entire fleet — with three algorithms, atomic Redis-backed counters, and sub-millisecond response. It accepts a single JSON payload and returns a structured response in milliseconds — no agents, plugins, or background workers required. The API is designed for synchronous, real-time use: call it inline in your request handler, CI step, or event pipeline and act on the result immediately.

Why do you need it?

Problem

  • In-process rate limiting fails immediately when you run more than one server instance — each instance has its own counter, so users get N× their intended quota across N servers.
  • Session-sticky load balancing can work around this, but breaks when servers restart, during deploys, and with any stateless architecture.
  • Building distributed rate limiting yourself requires managing Redis, handling race conditions, implementing multiple algorithms, and dealing with Redis failover — weeks of work for a non-differentiating feature.

Consequence

  • A user hitting 10 API servers with a 100 req/min limit effectively gets 1,000 req/min — 10× the intended quota. Paid tier abuse and DDoS attacks bypass your protection entirely.
  • Runaway API clients without effective rate limiting can saturate your database connection pool, causing cascading failures that affect all users — not just the abusive client.
  • Without token-bucket limiting on AI/LLM endpoints, a single user can exhaust your entire monthly API budget in hours — at current token costs, one bad actor can cost $10,000+ overnight.

Solution

  • Centralized, atomic rate limit state shared across your entire fleet — add as many servers as you need without any rate limit drift.
  • Three algorithms (fixed window, sliding window, token bucket) so you pick the right behavior for each use case rather than forcing one algorithm everywhere.
  • Drop-in: one API call per request, works in any language, no Redis infrastructure to manage.

Use cases

API tier enforcement

Enforce free/paid quotas per API key using a sliding window algorithm, so free users can't burst past their monthly limit regardless of traffic patterns.

Node.js — tier enforcement middleware

const API_KEY = process.env.DEVOPSIL_API_KEY;

async function rateLimitMiddleware(req, res, next) {
  const result = await fetch('https://devopsil.com/api/v1/ratelimit/increment', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      key: `api_key:${req.apiKey}`,
      algorithm: 'sliding_window',
      limit: getUserLimit(req.apiKey), // e.g. 1000 for free, 10000 for pro
      window_seconds: 3600, // per hour
    }),
  }).then(r => r.json());

  res.set('X-RateLimit-Remaining', result.remaining);
  if (!result.allowed) return res.status(429).json({ error: 'Rate limit exceeded' });
  next();
}

result.allowed is the boolean gate. result.remaining and result.reset_at populate standard rate limit headers for the client.

Login brute-force protection

Rate limit authentication attempts by IP address with a tight fixed window, automatically blocking brute-force attacks across your entire fleet.

Node.js — login rate limit

const API_KEY = process.env.DEVOPSIL_API_KEY;

async function checkLoginRateLimit(ipAddress: string) {
  const result = await fetch('https://devopsil.com/api/v1/ratelimit/increment', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      key: `login:${ipAddress}`,
      algorithm: 'fixed_window',
      limit: 10,
      window_seconds: 300, // 10 attempts per 5 minutes
    }),
  }).then(r => r.json());

  return result;
}

Return 429 with Retry-After header when result.allowed is false. result.reset_at gives the exact timestamp when the window resets.

AI/LLM cost control

Rate limit token-expensive endpoints by user with the token bucket algorithm, allowing short bursts while enforcing a sustainable average token spend per user.

Node.js — LLM token rate limit

const API_KEY = process.env.DEVOPSIL_API_KEY;

async function checkLlmRateLimit(userId: string, estimatedTokens: number) {
  const result = await fetch('https://devopsil.com/api/v1/ratelimit/increment', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      key: `llm:${userId}`,
      algorithm: 'token_bucket',
      limit: 100000,       // 100K tokens bucket capacity
      refill_rate: 10000,  // refill 10K tokens per minute
      cost: estimatedTokens,
    }),
  }).then(r => r.json());

  return result;
}

result.allowed gates the LLM call. result.remaining shows available token capacity. Burst traffic is absorbed by the bucket; sustained abuse is blocked.

Webhook send-rate control

Rate limit outbound webhook dispatches per tenant to prevent a high-volume tenant from overwhelming your dispatch infrastructure.

Node.js — outbound webhook throttle

const API_KEY = process.env.DEVOPSIL_API_KEY;

async function canDispatchWebhook(tenantId: string) {
  const result = await fetch('https://devopsil.com/api/v1/ratelimit/increment', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      key: `webhook_dispatch:${tenantId}`,
      algorithm: 'sliding_window',
      limit: 500,
      window_seconds: 60, // 500 dispatches per minute per tenant
    }),
  }).then(r => r.json());

  return result.allowed;
}

Queue the webhook for later if result.allowed is false. Use result.retry_after_ms to schedule the retry at the optimal time.

Export / bulk operation throttling

Limit expensive database export operations per user per hour to prevent one user from saturating your DB connection pool.

Node.js — export throttle

const API_KEY = process.env.DEVOPSIL_API_KEY;

async function checkExportLimit(userId: string) {
  const result = await fetch('https://devopsil.com/api/v1/ratelimit/increment', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      key: `export:${userId}`,
      algorithm: 'fixed_window',
      limit: 3,
      window_seconds: 3600, // 3 exports per hour
    }),
  }).then(r => r.json());

  return result;
}

result.allowed gates the export. result.reset_at tells the user exactly when they can try again.

DDoS mitigation

Rate limit by IP at the edge of your application before requests reach business logic, stopping volumetric attacks without per-request infrastructure overhead.

Node.js — edge IP rate limit

const API_KEY = process.env.DEVOPSIL_API_KEY;

async function edgeRateLimit(ip: string) {
  const result = await fetch('https://devopsil.com/api/v1/ratelimit/increment', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      key: `ip:${ip}`,
      algorithm: 'sliding_window',
      limit: 200,
      window_seconds: 60, // 200 req/min per IP
    }),
  }).then(r => r.json());

  return result;
}

Respond with 429 and no further processing if result.allowed is false. Sub-millisecond latency means this check adds negligible overhead.

Algorithm comparison

AlgorithmBest forWindow typeBurst allowed
fixed_windowSimple quotas, billing periodsHard resetYes
sliding_windowPer-minute / per-hour API limitsRollingNo
token_bucketBurst-tolerant throttling, AI tokensContinuousYes

How the API works

All requests use Bearer authentication. Your API key starts with rat_. Get one at /dashboard/api-keys.

Request

{
  "key": "api_key:ak_9x2mp3z",
  "algorithm": "sliding_window",
  "limit": 1000,
  "window_seconds": 3600
}

Response

{
  "allowed": true,
  "limit": 1000,
  "remaining": 847,
  "used": 153,
  "reset_at": "2024-03-15T15:00:00Z",
  "retry_after_ms": null,
  "algorithm": "sliding_window",
  "key": "api_key:ak_9x2mp3z"
}

Quick start

1

Get your API key

Create a free account and generate a key at /dashboard/api-keys. Your key starts with rat_.

2

Make your first call

Node.js

const API_KEY = process.env.DEVOPSIL_API_KEY; // starts with rat_

const result = await fetch('https://devopsil.com/api/v1/ratelimit/increment', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    key: 'user:usr_test_123',
    algorithm: 'sliding_window',
    limit: 100,
    window_seconds: 60,
  }),
}).then(r => r.json());

console.log(result.allowed, result.remaining);
3

Act on the result

Node.js — handle response

if (!result.allowed) {
  // Return 429 with standard headers
  res.set('Retry-After', Math.ceil(result.retry_after_ms / 1000));
  res.set('X-RateLimit-Limit', result.limit);
  res.set('X-RateLimit-Remaining', 0);
  return res.status(429).json({ error: 'Rate limit exceeded', reset_at: result.reset_at });
}

// Allowed — continue with the request
res.set('X-RateLimit-Remaining', result.remaining);

Frequently asked questions

Ready to integrate?

Free tier included. No credit card required.