Rate Limiting

Protect your tunnels from abuse and DoS attacks with request throttling

Overview

Rate Limiting policies control how many requests clients can make to your tunnel within a time window. Essential for API protection, preventing abuse, and ensuring fair resource usage.

Key Features

  • • Per-IP rate limits
  • • Global rate limits (all IPs combined)
  • • Configurable time windows (second/minute/hour)
  • • Burst allowance support
  • • Custom response codes (429 or 503)

Configuration Schema

FieldTypeDescription
requests_per_minuteNumber (required)Maximum number of requests allowed per minute. This is the base rate limit.
burstNumber (optional)Maximum burst size - extra requests allowed beyond the rate limit. Defaults to 2x requests_per_minute if not specified.
scopeString (optional)How to apply the rate limit:
  • "per_ip" (default): Separate limit per IP address
  • "per_subdomain": Shared limit across all IPs for this tunnel
  • "global": Single shared limit across all requests

How It Works

  • • Rate limiting uses a token bucket algorithm - requests consume tokens, tokens refill at the specified rate
  • Burst allows temporary spikes above the base rate (useful for handling traffic bursts)
  • • When the limit is exceeded, requests are blocked with a 429 Too Many Requests response
  • • Limits are tracked separately based on the scope setting
  • • Rate limits are applied per minute (converted internally to requests per second)

Configuration Examples

Example 1: Standard API Rate Limit

{
  "name": "Standard API Limits",
  "per_ip_limit": {
    "requests": 100,
    "window": "minute",
    "burst": 20
  },
  "response_code": 429,
  "retry_after": 60
}

Each IP can make 100 requests per minute, with a burst of 120.

Example 2: Strict DoS Protection

{
  "name": "DoS Protection",
  "per_ip_limit": {
    "requests": 10,
    "window": "second",
    "burst": 0
  },
  "response_code": 503,
  "retry_after": 1
}

Very strict: 10 requests per second per IP, no burst allowed.

Example 3: Global Traffic Limiter

{
  "name": "Global Traffic Cap",
  "global_limit": {
    "requests": 10000,
    "window": "hour"
  },
  "response_code": 503,
  "retry_after": 3600
}

Cap total traffic at 10,000 requests per hour across all users.

Example 4: Generous Limits for Development

{
  "name": "Development Limits",
  "per_ip_limit": {
    "requests": 1000,
    "window": "minute",
    "burst": 100
  },
  "response_code": 429,
  "retry_after": 10
}

Generous limits for testing: 1000/min + 100 burst.

Example 5: Combined IP + Global Limits

{
  "name": "Balanced Protection",
  "per_ip_limit": {
    "requests": 60,
    "window": "minute"
  },
  "global_limit": {
    "requests": 5000,
    "window": "minute"
  },
  "response_code": 429,
  "retry_after": 60
}

60/min per IP, 5000/min globally (protects both individual abuse and total load).

Response Headers

When rate limiting is active, NGSRV includes standard rate limit headers:

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1614556860
Retry-After: 60
HeaderDescription
X-RateLimit-LimitTotal requests allowed in window
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetUnix timestamp when limit resets
Retry-AfterSeconds until requests allowed again

Common Use Cases

API Protection

Prevent API abuse and ensure fair usage among clients.

DoS Prevention

Protect against denial-of-service attacks and traffic spikes.

Resource Management

Control backend load by limiting incoming request rate.

Cost Control

Prevent unexpected costs from runaway API usage.

Scraper Protection

Block aggressive scrapers and bots with strict per-IP limits.

How to Use

Step 1: Create Policy

Go to Dashboard → Security → Rate Limiting

  • Click "Create Policy"
  • Enter policy name and description
  • Configure per-IP limits (requests/window/burst)
  • Optionally configure global limits
  • Choose response code (429 or 503)
  • Save the policy

Step 2: Apply to Tunnel

ngsrv http 3000 --policy ngsrv_rate_ABC123

Step 3: Test Rate Limits

# Test with curl in a loop

for i in {1..150}; do curl -w "\n" https://myapp.tnl.ngsrv.com; done

You should see 429 responses after exceeding the limit.

Best Practices

✅ Start Conservative

Begin with stricter limits and relax them based on real usage patterns.

✅ Use 429 Status Code

429 is the standard HTTP status for rate limiting, most clients handle it correctly.

✅ Allow Reasonable Bursts

Burst allowance handles legitimate traffic spikes gracefully.

⚠️ Monitor and Adjust

Check audit logs regularly to ensure limits aren't blocking legitimate users.

💡 Combine with WAF

Use rate limiting together with WAF rules for comprehensive protection.