Skip to content

ecosyste-ms/conditional-rate-limit.lua

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 

conditional-rate-limit

Apache APISIX plugin for three-tier rate limiting used by Ecosyste.ms.

Overview

This plugin categorizes requests into three tiers with different rate limits:

  1. API Key - Users with API keys get the highest limits
  2. Polite - Users who include an email in their User-Agent or use the mailto parameter get moderate limits
  3. Anonymous - Everyone else gets the most restrictive limits

How Request Identification Works

The plugin identifies and tracks requests differently based on the tier:

  • API Key Tier: When an API key is provided (via header or query parameter), the rate limit is tracked per API key. Each unique API key has its own quota, regardless of the IP address making the request. This means multiple users or servers can share an API key and share the same rate limit quota.

  • Polite Tier: When an email address is detected (in the User-Agent header or mailto query parameter), the request is classified as "polite" but is still tracked by IP address. The email only determines which tier's limits apply - it does not become the identifier. Each unique IP address gets its own polite tier quota.

  • Anonymous Tier: All other requests are tracked by IP address with the anonymous tier limits.

Examples

  • Same IP with email → Gets polite tier limits, tracked by that IP
  • Same IP with API key → Gets API key tier limits, tracked by that specific key
  • Different IPs with same email → Each IP gets their own separate polite tier quota
  • Different IPs with same API key → Share the same API key quota

Exemptions

Requests to specific host domains can bypass rate limiting entirely. By default, grafana.ecosyste.ms, prometheus.ecosyste.ms, and apisix.ecosyste.ms are exempt. This ensures these services never get rate limited.

Exempt requests bypass rate limiting completely and don't receive rate limit headers.

Installation

  1. Clone the repository and copy the plugin to your APISIX container:
git clone https://github.com/ecosyste-ms/conditional-rate-limit.lua
docker cp ~/conditional-rate-limit.lua/conditional-rate-limit.lua apisix-quickstart:/usr/local/apisix/apisix/plugins
  1. Restart APISIX to load the new plugin:
docker restart apisix-quickstart
  1. Configure as a global rule via the APISIX Admin API:
curl -X PUT \
  http://YOUR_APISIX_IP:9180/apisix/admin/global_rules/1 \
  -H 'Content-Type: application/json' \
  -H "X-API-KEY: YOUR_ADMIN_API_KEY" \
  -d '{
    "plugins": {
      "conditional-rate-limit": {
        "api_key_count": 50000,
        "api_key_time_window": 3600,
        "polite_count": 15000,
        "polite_time_window": 3600,
        "anonymous_count": 5000,
        "anonymous_time_window": 3600,
        "key_header": "X-API-Key",
        "key_query_param": "apikey",
        "mailto_query_param": "mailto",
        "email_pattern": "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}"
      }
    }
  }'

Configuration

plugins:
  conditional-rate-limit:
    enable: true
    config:
      # API Key tier
      api_key_count: 1000
      api_key_time_window: 60

      # Polite tier
      polite_count: 100
      polite_time_window: 60

      # Anonymous tier
      anon_count: 10
      anon_time_window: 60

      # API key detection
      key_header: "X-API-Key"
      key_query_param: "apikey"

      # Email detection for polite tier
      mailto_query_param: "mailto"
      email_pattern: "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}"

      # Response
      rejected_code: 429
      rejected_msg: "Too many requests"

      # Exemptions (optional)
      exempt_hosts:           # Defaults to ["grafana.ecosyste.ms", "prometheus.ecosyste.ms", "apisix.ecosyste.ms"]
        - "grafana.ecosyste.ms"
        - "prometheus.ecosyste.ms"
        - "apisix.ecosyste.ms"

Examples

# API key - 1000 req/min
curl -H "X-API-Key: your-key" https://api.ecosyste.ms/endpoint

# Polite - 100 req/min (via User-Agent)
curl -H "User-Agent: MyApp/1.0 (contact: user@example.com)" https://api.ecosyste.ms/endpoint

# Polite - 100 req/min (via mailto parameter)
curl "https://api.ecosyste.ms/endpoint?mailto=you@example.com"

# Anonymous - 10 req/min
curl https://api.ecosyste.ms/endpoint

License

GNU Affero General Public License v3.0 - see LICENSE file.

About

Apache APISIX plugin for three-tier rate limiting used by Ecosyste.ms.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

  •  

Languages