Skip to main content

a6-plugin-limit-count

Overview

The limit-count plugin rate-limits requests using a fixed-window counter algorithm. Define a maximum number of requests (count) within a time interval (time_window). Supports per-IP, per-consumer, per-header, or custom variable keys. For distributed APISIX deployments, use Redis or Redis-cluster as the shared counter backend.

When to Use

  • Simple request counting (e.g., 100 requests per hour)
  • API quota enforcement per consumer or API key
  • Shared rate limits across multiple APISIX nodes (via Redis)
  • Grouped quotas across multiple routes

Plugin Configuration Reference

Core Fields

FieldTypeRequiredDefaultDescription
countintegerYes*Max requests allowed in the time window. > 0
time_windowintegerYes*Time window in seconds. > 0
key_typestringNo"var"Key type: "var", "var_combination", or "constant"
keystringNo"remote_addr"Variable name or combination for counting
rejected_codeintegerNo503HTTP status on rejection (200–599)
rejected_msgstringNoCustom rejection message body
groupstringNoShare counters across routes with same group ID
policystringNo"local"Storage: "local", "redis", or "redis-cluster"
show_limit_quota_headerbooleanNotrueInclude X-RateLimit-* headers in responses
allow_degradationbooleanNofalseAllow requests when plugin fails

*Required unless using rules array.

Redis Fields (when policy: "redis")

FieldTypeRequiredDefaultDescription
redis_hoststringYesRedis server address
redis_portintegerNo6379Redis port
redis_usernamestringNoRedis ACL username
redis_passwordstringNoRedis password
redis_databaseintegerNo0Redis database index
redis_timeoutintegerNo1000Timeout in milliseconds
redis_sslbooleanNofalseEnable TLS to Redis

Redis Cluster Fields (when policy: "redis-cluster")

FieldTypeRequiredDefaultDescription
redis_cluster_nodesarray[string]YesArray of "host:port" (min 2)
redis_cluster_namestringYesCluster name
redis_passwordstringNoCluster password
redis_timeoutintegerNo1000Timeout in milliseconds
redis_cluster_sslbooleanNofalseEnable TLS

Key Types

key_typekey FormatExampleDescription
"var"NGINX variable (no $)"remote_addr"Single variable
"var_combination"$var1 $var2"$remote_addr $consumer_name"Multiple variables combined
"constant"Any string"global"Same counter for all requests

Response Headers

When show_limit_quota_header: true (default):

HeaderDescription
X-RateLimit-LimitTotal quota for the time window
X-RateLimit-RemainingRemaining requests in current window
X-RateLimit-ResetSeconds until counter resets

Step-by-Step: Basic Rate Limiting

1. Rate limit by client IP (route-level)

a6 route create -f - <<'EOF'
{
"id": "rate-limited-api",
"uri": "/api/*",
"plugins": {
"limit-count": {
"count": 100,
"time_window": 60,
"key_type": "var",
"key": "remote_addr",
"rejected_code": 429,
"rejected_msg": "Rate limit exceeded. Try again later."
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"backend:8080": 1
}
}
}
EOF

100 requests per 60 seconds per client IP.

2. Rate limit per consumer

a6 consumer create -f - <<'EOF'
{
"username": "free-tier",
"plugins": {
"limit-count": {
"count": 100,
"time_window": 3600,
"rejected_code": 429
}
}
}
EOF

a6 consumer create -f - <<'EOF'
{
"username": "premium",
"plugins": {
"limit-count": {
"count": 10000,
"time_window": 3600,
"rejected_code": 429
}
}
}
EOF

Consumer-level limits apply across all routes the consumer accesses.

Common Patterns

Shared quota across routes (group)

{
"plugins": {
"limit-count": {
"count": 1000,
"time_window": 3600,
"group": "api-v1",
"rejected_code": 429
}
}
}

All routes with "group": "api-v1" share the same 1000 req/hour counter. Important: All routes in a group must have identical limit-count config.

Multi-variable key (IP + consumer)

{
"plugins": {
"limit-count": {
"count": 50,
"time_window": 60,
"key_type": "var_combination",
"key": "$remote_addr $consumer_name",
"rejected_code": 429
}
}
}

Global rate limit (all requests share one counter)

{
"plugins": {
"limit-count": {
"count": 10000,
"time_window": 60,
"key_type": "constant",
"key": "global",
"rejected_code": 429
}
}
}

Distributed rate limiting with Redis

{
"plugins": {
"limit-count": {
"count": 1000,
"time_window": 60,
"key": "remote_addr",
"policy": "redis",
"redis_host": "redis.example.com",
"redis_port": 6379,
"redis_password": "secret",
"redis_database": 0,
"redis_ssl": true,
"rejected_code": 429
}
}
}

Use Redis when running multiple APISIX nodes to share counters.

Redis cluster

{
"plugins": {
"limit-count": {
"count": 1000,
"time_window": 60,
"key": "remote_addr",
"policy": "redis-cluster",
"redis_cluster_nodes": [
"192.168.1.10:6379",
"192.168.1.11:6379",
"192.168.1.12:6379"
],
"redis_cluster_name": "apisix-cluster",
"redis_password": "secret",
"rejected_code": 429
}
}
}

Troubleshooting

SymptomCauseFix
Limits not shared across APISIX nodesUsing policy: "local" (default)Switch to "redis" or "redis-cluster"
Group config rejectedMismatched configs in same groupEnsure all routes in group have identical limit-count config
Unexpected counter resetFixed-window boundaryNormal behavior — counters reset at fixed intervals
Key empty, all clients share one counterVariable doesn't existVerify key variable name; falls back to remote_addr
Rate limit headers missingshow_limit_quota_header: falseSet to true (default)
503 instead of 429Default rejected_code is 503Set rejected_code: 429 explicitly

Fixed-Window Algorithm Note

limit-count uses a fixed-window algorithm. Counters reset at exact intervals. This means a burst at the boundary of two windows can temporarily exceed the intended rate (e.g., 100 req/min allows 200 requests if 100 come at t=59s and 100 at t=61s). For smoother rate limiting, combine with limit-req (leaky bucket).

Config Sync Example

version: "1"
consumers:
- username: free-tier
plugins:
limit-count:
count: 100
time_window: 3600
rejected_code: 429
routes:
- id: rate-limited-api
uri: /api/*
plugins:
limit-count:
count: 1000
time_window: 60
key: remote_addr
rejected_code: 429
upstream_id: api-upstream
upstreams:
- id: api-upstream
type: roundrobin
nodes:
"backend:8080": 1

This page is generated from a6-plugin-limit-count/SKILL.md in the api7/a6 repository. Browse all skills on the AI Agent Skills page.

API7.ai Logo

The digital world is connected by APIs,
API7.ai exists to make APIs more efficient, reliable, and secure.

Sign up for API7 newsletter

Product

API7 Gateway

SOC2 Type IIISO 27001HIPAAGDPRRed Herring

Copyright © APISEVEN PTE. LTD 2019 – 2026. Apache, Apache APISIX, APISIX, and associated open source project names are trademarks of the Apache Software Foundation