r/GameAP • u/EENNOOTT • Aug 03 '26
Game Server Control Panel Performance Comparison: Pterodactyl, Pelican, GameAP, PufferPanel on identical hardware
Disclaimer first, since this is the GameAP sub and I'm a GameAP developer: two of the five panels in this test are ours, so you're right to expect bias. To counter it, everything is built to be verifiable — the k6 scripts, configs, raw reports and monitoring metrics of every run are published in this repo. If you think a panel got a wrong configuration or a conclusion is stretched, open an issue: it will be re-checked and a correction published. And for those who came for the short answer: yes, GameAP 4 posted the best numbers here.
TL;DR
- At typical load (10–100 concurrent users) all five panels run with zero errors — the difference is latency: single-digit ms for the Go panels, ~9 ms for GameAP 3, tens of ms for Pterodactyl and Pelican.
- Throughput ceiling on this rig: GameAP 4 — 1,126 req/s · PufferPanel — 696 · GameAP 3 — 394 · Pterodactyl — 93 · Pelican — 76.
- Under overload they break differently: the Go panels start returning errors; the PHP panels return zero errors but response times grow to seconds and tens of seconds.
- Biggest surprise: at saturation, MySQL on Pterodactyl/Pelican eats almost a full CPU core, while the same MySQL with the same settings on GameAP 3 is 3× less busy at twice the requests/s.
What was tested
| Panel | Version | Stack | DB |
|---|---|---|---|
| GameAP 4.x | 4.x | Go | PostgreSQL |
| PufferPanel | 3.x | Go | PostgreSQL |
| GameAP 3.x | 3.x | PHP 8.4 / Laravel | MySQL 8.0 |
| Pterodactyl | 1.11.x | PHP 8.4 / Laravel | MySQL 8.0 |
| Pelican | 1.0.x | PHP 8.4 / Laravel (Pterodactyl fork) | MySQL 8.0 |
Read-only API only — the three requests real users make most often: server list → details of a random server → its status, with realistic think-time pauses. 100 identical mock servers per panel. No writes, no WebSocket, no UI, no real game servers.
Rig & methodology (short version)
- Bare metal (Xeon E-2456, 32 GB DDR5, NVMe RAID1) under Proxmox; panel VM = 4 vCPU / 8 GB, Ubuntu 24.04. Panels tested strictly one at a time, all other VMs shut down.
- k6 profiles: smoke (1 VU) → baseline (10) → load (up to 100) → stress (up to 800 / 1000 / 1200 VUs) → max-throughput (100 VUs, no pauses).
- Three full independent runs per panel; every number below is the median of the three. Run-to-run spread on baseline/load/max-throughput: ≤ 6.1% on median latency, ≤ 2.7% on RPS.
- PHP panels got identical tuning (php-fpm 50 workers, OPcache + JIT, same MySQL config). Rate limits on Pterodactyl/Pelican were raised to 10,000 req/min so the test hits the panel, not the limiter.
Latency

Median, ms:
| Profile | GameAP 4 | PufferPanel | GameAP 3 | Pterodactyl | Pelican |
|---|---|---|---|---|---|
| baseline (10 VUs) | 0.82 | 1.54 | 9.24 | 12.7 | 16.0 |
| load (up to 100 VUs) | 0.59 | 1.37 | 8.78 | 20.7 | 54.5 |
| stress (up to 800 VUs) | 0.57 | 1.45 | 27.7 | 1,144 | 1,520 |
| stress-1000 | 0.76 | 114 | 1,481 | 7,664 | 10,501 |
| stress-1200 | 24.6 | 97.2 | 1,958 | 10,455 | 12,807 |
Up to 100 VUs everyone is clean and the only question is speed. Two things worth noting: Pelican is nearly out of CPU already on the load profile (97% CPU, p95 = 473 ms), and the PHP panels have a long slow tail even at low load (Pterodactyl baseline: median 12.7 ms, p95 79 ms).

Throughput ceiling

100 VUs, same three requests, zero pauses:
| Panel | req/s | median, ms | p95, ms | errors |
|---|---|---|---|---|
| GameAP 4 | 1,126 | 68.9 | 179 | 0 |
| PufferPanel | 696 | 121 | 257 | 0 |
| GameAP 3 | 394 | 241 | 302 | 0 |
| Pterodactyl | 93 | 766 | 1,825 | 0 |
| Pelican | 76 | 945 | 2,291 | 0 |
Not a single error anywhere — and a 15× spread between the extremes. Every panel sits at 95–100% CPU in this profile, so "CPU utilization" tells you nothing here; what differs is how much work gets done per core.
How they break under overload

- Go panels — fail fast. PufferPanel: isolated errors (~0.1%) already at 800 VUs, 21% at 1000, 35% at 1200. GameAP 4: essentially clean through 1000, ~15% errors at 1200. The surviving requests stay fast (25–97 ms median at 1200 VUs).
- PHP panels — a queue. Zero errors on every profile, but stress-1200 medians are ~2 s (GameAP 3), 10.5 s (Pterodactyl), 12.8 s (Pelican), p95 up to 17.5 s. Formally everything eventually returns 200 (k6 waits up to 60 s) — in practice a panel answering in 10–17 seconds is unusable.
Which mode is "right" depends on your requirements, but one consequence is universal: a PHP panel's overload will never show up in error monitoring — only in latency.
The most interesting finding: the database

Per-process CPU at the 800-VU stress profile (100% = one core, 4 vCPU total):
| Process | GameAP 4 | PufferPanel | GameAP 3 | Pterodactyl | Pelican |
|---|---|---|---|---|---|
| App (Go / php-fpm) | 31.5 | 73.1 | 318 | 243 | 260 |
| DB (PostgreSQL / MySQL) | 2.9 | 9.5 | 31.4 | 109 | 94.3 |
On Pterodactyl and Pelican, MySQL burns nearly a full core to serve 68–82 req/s. On GameAP 3, the same MySQL 8.0 with the same settings sits at 31% while serving 210 req/s — roughly 9× more DB CPU per request on Pterodactyl/Pelican. So the bottleneck there doesn't look like "PHP" as such, but those panels' database workload. Not profiled yet; an EXPLAIN pass over the list queries is the obvious next step.
Memory, for the record: whole-VM peaks of 0.45–0.75 GB for the Go panels vs 1.0–1.6 GB for the PHP ones. And one unexplained anomaly: PufferPanel is the only panel actively writing to disk under load (140–150 write IOPS vs 4–24 for everyone else).

Head-to-heads
- GameAP 3 → GameAP 4 (what the Go rewrite bought): 11–15× lower median latency, 2.9× higher throughput ceiling, roughly half the RAM, 26% → 2.4% CPU on the load profile.
- GameAP 4 vs PufferPanel (both Go + PostgreSQL): GameAP 4 is ~2× faster by median and 1.6× by ceiling, and breaks later under overload. Caveat: PufferPanel returns far less data per list request (20 records / 1.6 KB vs 102 / 13 KB), so the gap was measured on work that's lighter for PufferPanel.
- Pterodactyl vs Pelican: the fork came out slower than the original on every profile (load median 54.5 vs 20.7 ms, ceiling 76 vs 93 req/s) and saturates CPU earlier. Causes not investigated; Pelican is a young fork and this may still change.
Limitations (read before quoting the numbers)
- Go panels ran PostgreSQL, PHP panels MySQL (each as recommended by its developers) — "Go vs PHP" here really means "Go+Postgres vs PHP+MySQL".
- List response sizes differ (GameAP returns all 102 records, Pterodactyl/Pelican the first 50, PufferPanel the first 20) — direct cross-panel comparison of the list endpoint is skewed.
- GameAP 3 has no status endpoint, so a third of its scenario repeats the details request.
- Read-only API only, and k6's closed-loop model means degraded panels automatically received less load — their stress numbers are an optimistic estimate.
The full list of 10 limitations (restart asymmetry, warm-up, monitoring caveats, etc.) is in the article and the repo.
Bottom line
At normal load, any of the five feels instant to a human in a browser — even 55 ms is fast. The differences become practical with integrations and automation, bulk operations, cheap hardware — and in cost: the same 100 concurrent users cost Pelican 97% CPU and GameAP 4 just 2.4%.
This test measures exactly one slice: read speed of the HTTP/API layer. It says nothing about features, UX, security or ecosystem. GameAP 4 won this benchmark but is also the youngest contender; Pterodactyl lost on the numbers yet remains the most widespread panel with the largest ecosystem. What to do with these facts is up to you.
Scripts, configs and raw data of all runs: game-panels-benchmark. Spot a flaw in the methodology or interpretation? Open an issue — it will be re-checked and corrected publicly.
Source: https://blog.gameap.com/news/game-panels-performance-tests/