Performance benchmarks comparing GraphQL gateway implementations across federation and composite schema approaches.
Latest Results: Constant Load | Ramping Load
Each benchmark runs a gateway against 4 subgraphs (Accounts, Inventory, Products, Reviews) and executes a heavy nested query. The subgraph implementation differs per schema approach:
Subgraphs are built with Rust using async-graphql + axum.
Gateways:
- Apollo Gateway (Node.js)
- Apollo Router (Rust)
- Cosmo (Go)
- Grafbase (Rust)
- Hive Gateway (Node.js)
- Hive Gateway Router Runtime (Node.js)
- Hive Router (Rust)
Subgraphs are built with .NET using HotChocolate.
Gateways:
- HotChocolate (.NET)
- k6 - auto-installed if missing (via Homebrew on macOS, apt on Linux)
- jq - required by the monitor script
- python3 - used for JSON parsing
- curl - used for health checks
- Gateway-specific dependencies are installed automatically by each gateway's
install.sh
./k6/benchmark.sh <gateway-path> [subgraphs-dir] [constant|ramping]Examples:
# HotChocolate gateway, constant load (default), .NET subgraphs
./k6/benchmark.sh composite-schema/gateways/hotchocolate
# HotChocolate gateway with Rust subgraphs
./k6/benchmark.sh composite-schema/gateways/hotchocolate subgraphs-rust
# Cosmo gateway, ramping load
./k6/benchmark.sh apollo-federation/gateways/cosmo ramping- Installs dependencies for the subgraphs and gateway (
install.sh) - Starts subgraphs in the background
- Starts the gateway and waits for it to become healthy
- Runs a warmup phase (15s by default)
- Starts a CPU/memory monitor, then runs the k6 benchmark (60s by default)
- Saves results and cleans up all processes
Environment variables:
| Variable | Default | Description |
|---|---|---|
WARMUP_SECONDS |
15 |
Warmup duration before measurement |
MEASURE_SECONDS |
60 |
Benchmark measurement duration |
BENCH_VUS |
50 (constant) / 500 (ramping) |
Number of virtual users |
BENCH_RUNS |
3 |
Iterations per benchmark (median selected for results) |
On Linux with taskset available, the script reads profiles.json to pin k6, the gateway, and subgraphs to specific CPU cores. Profiles are defined for 8-core and 16-core machines. On macOS, CPU pinning is skipped.
Each run produces a timestamped results directory:
<gateway-dir>/results/<timestamp>/
data.csv # time-series: CPU, RSS, VUs, RPS, P95, success rate
k6_summary.json # full k6 metrics (machine-readable)
k6_summary.txt # k6 summary (human-readable)
This benchmark repository is based on the work by The Guild on graphql-gateways-benchmark.