Benchmarks
All benchmarks are reproducible. Run them on your hardware — see Reproduce below.
Test setup (March 4, 2026 run)
- Hardware: AWS c7i.2xlarge (8 vCPU, 16 GB RAM)
- OS: Ubuntu 24.04.3 LTS
- Fairvisor: latest
mainfromgithub.com/fairvisor/edge - OpenResty: 1.29.2.1 (native, no Docker)
- Load generator: k6 v0.54.0 (
constant-arrival-rate) - Profile: 10,000 RPS steady state, 60s run, 10s warmup
- Topology: single-host benchmark (SUT + k6 on one VM), CPU-isolated with
taskset- OpenResty/backend: cores
0-3 - k6: cores
4-7
- OpenResty/backend: cores
- Decision API method:
POST /v1/decisionwithX-Original-MethodandX-Original-URI - Reverse proxy path: includes enforcement + upstream proxy hop to backend nginx
Latency
Results at 10,000 RPS (steady state):
| Percentile | Fairvisor (decision only) | Fairvisor (reverse proxy) | Raw Nginx (no rate limiting) |
|---|---|---|---|
| p50 | 112μs | 241μs | 71μs |
| p90 | 191μs | 376μs | 190μs |
| p99 | 426μs | 822μs | 446μs |
| p99.9 | 2.99ms | 2.98ms | 1.61ms |
For this run, decision_service reached sub-millisecond p99 (426μs) on single-host setup with CPU pinning.
Throughput
Max sustained throughput (single edge):
| Configuration | Max RPS |
|---|---|
| Simple rate limit (1 rule) | 110,500 |
| Complex policy (5 rules, JWT parsing, loop detection) | 67,600 |
| With token estimation | 49,400 |
Memory (reference sizing)
The following memory profile is retained as a sizing reference for active limiter keys:
| Active limit keys | Memory usage |
|---|---|
| 1,000 | 48 MB |
| 10,000 | 120 MB |
| 100,000 | 680 MB |
| 1,000,000 | 5.2 GB |
Memory scales roughly linearly with active limit keys because each key keeps a small fixed token-bucket state.
Reproduce
git clone https://github.com/fairvisor/benchmark
cd benchmark
./run-all.sh
Results are published with every release.