Este artículo trata sobre las pruebas de carga de cinco populares paneles de control de servidores de juegos: GameAP 3, GameAP 4, PufferPanel, Pterodactyl y Pelican. Todos los paneles se prueban en el mismo hardware, en condiciones lo más parecidas posible; allí donde las condiciones no pudieron igualarse, se indica explícitamente en las limitaciones.

Aviso. Este artículo se publica en el blog de GameAP, y su autor es un desarrollador; GameAP 3 y GameAP 4 son dos de los cinco paneles sometidos a prueba. Esto supone un conflicto de intereses, y es legítimo esperar parcialidad. Para contrarrestarla, toda la prueba está construida para ser verificable: los scripts de k6, las configuraciones, los informes sin procesar de k6 y las métricas de monitorización de cada ejecución están publicados en un repositorio de GitHub. La metodología puede examinarse paso a paso, y la prueba puede repetirse en su propio hardware. Si cree que algún panel recibió una configuración incorrecta o que alguna conclusión está forzada, abra un issue: se volverá a comprobar y se publicará una corrección. Y una nota para quienes vinieron por la respuesta corta: sí, GameAP 4 obtuvo aquí las mejores cifras.

En resumen:

  • Con carga típica (10–100 usuarios concurrentes), los cinco paneles funcionan sin un solo error; lo que difiere es la latencia: milisegundos de un solo dígito para los paneles Go, alrededor de 9 ms para GameAP 3, decenas de milisegundos para Pterodactyl y Pelican.
  • El techo de rendimiento en este banco de pruebas:
    • 1126 peticiones/s para GameAP 4
    • 696 peticiones/s para PufferPanel
    • 394 peticiones/s para GameAP 3
    • 93 peticiones/s para Pterodactyl
    • y 76 peticiones/s para Pelican
  • Bajo sobrecarga, los paneles fallan de forma distinta: los paneles Go empiezan a devolver errores; los paneles PHP no devuelven ningún error, pero los tiempos de respuesta crecen hasta segundos y decenas de segundos.
  • La mayor sorpresa: en saturación, MySQL en Pterodactyl y Pelican consume casi un núcleo de CPU completo, mientras que en GameAP 3, con el mismo MySQL y los mismos ajustes, la base de datos está tres veces menos ocupada con el doble de peticiones por segundo.
Techo de rendimientocuanto mayor, mejorpeticiones por segundo · mediana de tres ejecuciones2505007501 0001 2500GameAP 4.x: 1 126 peticiones/s1 126GameAP 4.xPufferPanel: 696 peticiones/s696PufferPanelGameAP 3.x: 394 peticiones/s394GameAP 3.xPterodactyl: 93 peticiones/s93PterodactylPelican: 76 peticiones/s76Pelican

Objetivos #

  1. Encontrar el punto de ruptura: el límite hasta el cual un panel sigue funcionando correctamente.
  2. Comparar las alternativas en condiciones lo más parecidas posible.
  3. Comparar GameAP 3 y GameAP 4: qué consiguió exactamente la reescritura de PHP a Go.

Además de la comparación general de los cinco paneles, tres duelos directos resultan de especial interés:

  1. GameAP 3.x vs GameAP 4.x: una reescritura completa en Go con una arquitectura actualizada.
  2. GameAP 4.x vs PufferPanel: una comparación de paneles escritos en Go.
  3. Pterodactyl vs Pelican: el panel original frente a su fork.

Los paneles #

PanelVersiónStackBase de datosDaemon
GameAP 4.x4.xGoPostgreSQLgameap-daemon
PufferPanel3.xGoPostgreSQLintegrado
GameAP 3.x3.xPHP 8.4 / LaravelMySQL 8.0gameap-daemon
Pterodactyl1.11.xPHP 8.4 / LaravelMySQL 8.0Wings (Docker)
Pelican1.0.xPHP 8.4 / Laravel, fork de PterodactylMySQL 8.0Wings (Docker)

Los tres paneles PHP ejecutan además Redis (caché y sesiones). Las versiones se registran a nivel de rama mayor a fecha de abril de 2026, cuando se realizaron las ejecuciones.

Qué se pone a prueba #

  • latencia HTTP/API en distintos niveles de concurrencia: pruebas de carga (10–100 VUs);
  • comportamiento bajo sobrecarga (degradación, errores, consumo de recursos): pruebas de estrés (800–1200 VUs);
  • el techo de rendimiento sin pausas entre peticiones: pruebas de rendimiento.

Fuera del alcance de este artículo:

  • peticiones de escritura;
  • UX, funcionalidades, seguridad, ecosistema;
  • el trabajo con servidores de juegos reales y sus archivos;
  • estabilidad a largo plazo: no se ejecutaron pruebas soak ni spike.

Banco de pruebas #

Servidor (bare-metal, Selectel):

  • CPU: Intel Xeon E-2456 (Raptor Lake, 6C/12T, 3,3 GHz base / 5,1 GHz turbo, 18 MB L3);
  • RAM: 32 GB DDR5 ECC (2×16 GB, 4400 MT/s);
  • almacenamiento: 2× Samsung 990 PRO 1TB NVMe en mdadm RAID1;
  • hipervisor: Proxmox VE 9.1.5 sobre Debian 13, kernel 6.17.9-1-pve.
Bare-metal · Selectel · Xeon E-2456 · 32 GB DDR5 · Proxmox VE 9k6-runner4 vCPU · 4 GBgenerador de cargaPanel (API)4 vCPU · 8 GB · 40 GBUbuntu 24.04 LTSDaemon / agente6 vCPU · 12 GB · 80 GBUbuntu 24.04 LTSMonitorización2 vCPU · 4 GBPrometheus + GrafanaHTTPmétricas: node_exporter → Prometheus

Configuración de las máquinas virtuales #

VMvCPURAMDiscoRol
Panel48 GB40 GBpanel de control (API), Ubuntu 24.04 LTS
Daemon612 GB80 GBdaemon/agente de servidores de juegos, Ubuntu 24.04 LTS
k6-runner44 GBgenerador de carga
Monitorización24 GBPrometheus + Grafana

Ajustes del host #

  • gobernador de CPU: performance;
  • C-states limitados a C1;
  • Turbo Boost activado;
  • swap desactivado en todas las máquinas virtuales.

Metodología #

Los paneles se prueban de uno en uno: mientras un panel está en prueba, todas las demás VM están apagadas para evitar interferencias. Durante una ejecución, lo único que funciona es el panel (API), el daemon de servidores de juegos, el generador de carga k6 y la pila de monitorización.

Cada panel pasó por tres ejecuciones completas e independientes de toda la serie de perfiles (18–19 de abril de 2026). Todas las cifras de este artículo son medianas de las tres ejecuciones, salvo que se indique explícitamente lo contrario.

La secuencia para cada panel: arrancar sus dos VM (panel y daemon) → reiniciar los servicios → una ejecución de calentamiento del escenario smoke (1 VU, 30 s) → los perfiles de carga en orden. Antes de cada perfil se reinician los servicios del panel; después de cada perfil hay una pausa de 60 segundos. Los conjuntos de servicios reiniciados difieren entre paneles: para los paneles PHP son php-fpm, nginx y MySQL (más Redis en GameAP 3); para PufferPanel, la propia aplicación; para GameAP 4, solo nginx. Esta es una asimetría de la metodología; más detalles en las limitaciones.

Perfiles de carga #

PerfilVUsDuraciónTipo de prueba
smoke130 slatencia sin concurrencia
baseline104,5 mincarga
load20 → 50 → 10011 mincarga
stress50 → 100 → 200 → 400 → 80010 minestrés
stress-1000200 → 500 → 1000, mantenido 5 min9 minestrés
stress-1200200 → 500 → 800 → 1200, mantenido 5 min10 minestrés
max-throughput100, sin think-time2 min 40 srendimiento

Escenario #

Cada iteración realiza tres peticiones GET, las que los usuarios reales hacen con más frecuencia: la lista de servidores, los detalles de un servidor aleatorio de esa lista y su estado. Hay una pausa de 0,3–0,8 s entre peticiones y una pausa de 1–3 s al final de la iteración. El perfil max-throughput ejecuta las mismas tres peticiones sin pausas. No hay peticiones que modifiquen datos (POST, PUT, DELETE, etc.) en la prueba.

PanelListaDetallesEstadoElementos en la respuesta de lista
GameAP 3.x/api/servers/api/servers/{id}la misma petición que detalles¹102
GameAP 4.x/api/servers/api/servers/{id}/api/servers/{id}/status102
PufferPanel/api/servers/api/servers/{id}/api/servers/{id}/status20 (primera página)
Pterodactyl/api/client/api/client/servers/{id}…/{id}/resources50 (primera página)
Pelican/api/client/api/client/servers/{id}…/{id}/resources50 (primera página)

¹ GameAP 3.x no tiene un endpoint de estado separado: se repite la petición de detalles.

Cada panel recibió 100 servidores de juegos ficticios idénticos (un script de relleno que imprime la hora; los servidores nunca se instalaron ni se iniciaron). Las respuestas de las API de lista difieren, sin embargo: GameAP devuelve todos los registros de una vez (la base de datos del banco de pruebas contenía 102), Pterodactyl y Pelican devuelven la primera página de 50, PufferPanel la primera página de 20. El tamaño medio de respuesta en el perfil load es de 13–16 KB por petición para cuatro paneles y de 1,6 KB para PufferPanel. Por tanto, una comparación directa de la latencia de list_servers entre paneles no es del todo justa: es una de las principales salvedades de esta prueba.

Autenticación y límites #

GameAP 3/4, Pterodactyl y Pelican utilizan una clave de API (Bearer). PufferPanel utiliza OAuth2 client credentials: el token se obtiene una vez en setup() y lo reutilizan todos los VUs. La propia petición OAuth (~58 ms) aparece en las estadísticas de cada perfil, porque setup() se ejecuta en cada invocación de k6. En el corto perfil smoke (31–34 peticiones) eleva la latencia media de PufferPanel de ~2 a ~3,7 ms, mientras la mediana no se mueve. En baseline es una petición de ~2 200, aproximadamente +0,03 ms (~2 %) en la media, con la mediana y los percentiles intactos; en los perfiles más largos el efecto es despreciable.

En Pterodactyl y Pelican, los límites de tasa de la API se elevaron a 10 000 peticiones por minuto; de lo contrario, la prueba habría topado con el limitador y no con el panel.

Ajustes de los paneles PHP (idénticos en GameAP 3, Pterodactyl y Pelican) #

; PHP-FPM
pm = dynamic, pm.max_children = 50, pm.start_servers = 10
; OPcache
opcache.memory_consumption = 256, opcache.jit = tracing, opcache.jit_buffer_size = 128M
; MySQL
innodb_buffer_pool_size = 2G, max_connections = 200, innodb_flush_log_at_trx_commit = 2

Herramientas #

  • k6 v1.7.1; el tiempo de espera de petición por defecto es de 60 s;
  • Prometheus, node_exporter 1.8.2 (métricas de VM, paso de 15 s), process_exporter 0.8.7 (métricas de procesos, paso de 30 s).

El modelo de carga de bucle cerrado #

k6 utiliza un modelo de bucle cerrado: un usuario virtual no envía la siguiente petición hasta haber recibido la respuesta a la anterior. Cuando un panel se ralentiza, la intensidad de carga real desciende automáticamente. En un sistema abierto —usuarios reales, paneles que se actualizan automáticamente, integraciones— las peticiones seguirían llegando con independencia de las respuestas, y a un panel degradado le iría aún peor. Téngalo en cuenta al leer los resultados de estrés: las cifras de los paneles ralentizados son una estimación optimista. Más sobre el efecto: coordinated omission.

Observaciones del montaje del banco de pruebas #

Recursos de la VM del panel durante el perfil smoke: 1 VU, con la base de datos ya cargada con 100 servidores; pico en la ventana del perfil, mediana de tres ejecuciones:

PanelCPURAM
GameAP 4.x0,4 %449 MB
PufferPanel0,6 %462 MB
GameAP 3.x3,2 %1 049 MB
Pterodactyl2,3 %1 096 MB
Pelican2,9 %1 177 MB

La RAM corresponde a toda la máquina virtual (MemTotal − MemAvailable), incluidos el SO, la base de datos y los servicios auxiliares.

Observaciones recogidas durante el montaje del banco de pruebas:

  • Pterodactyl y Pelican no pueden funcionar detrás de NAT, ni el panel ni Wings: el navegador se conecta a Wings directamente por HTTP/HTTPS.
  • Pelican requiere reconstruir su caché de configuración tras los cambios de ajustes; de lo contrario, el panel falla.

Resultados #

Todas las cifras siguientes son medianas de tres ejecuciones; los informes sin procesar de cada ejecución están en el repositorio. Sobre la reproducibilidad: en los perfiles baseline, load y max-throughput, la latencia mediana difiere entre ejecuciones como máximo un 6,1 %, y el RPS como máximo un 2,7 %. El smoke es demasiado corto (28–34 peticiones por ejecución), así que la dispersión de su mediana alcanza el 22 %. En los perfiles de estrés el comportamiento es, como era de esperar, menos estable: la mediana de stress-1200 de GameAP 4 en las distintas ejecuciones, por ejemplo, fue 23,7 / 24,6 / 31,9 ms.

Latencia por nivel de carga #

Latencia mediana por nivel de cargacuanto menor, mejorms, escala logarítmica · mediana de tres ejecuciones1 ms10 ms100 ms1 s10 s11010080010001200máximo de VUs objetivo del perfilGameAP 4.x — 1 VUs: 1,11 msGameAP 4.x — 10 VUs: 0,82 msGameAP 4.x — 100 VUs: 0,59 msGameAP 4.x — 800 VUs: 0,57 msGameAP 4.x — 1000 VUs: 0,76 msGameAP 4.x — 1200 VUs: 24,6 msPufferPanel — 1 VUs: 2,01 msPufferPanel — 10 VUs: 1,54 msPufferPanel — 100 VUs: 1,37 msPufferPanel — 800 VUs: 1,45 msPufferPanel — 1000 VUs: 114 msPufferPanel — 1200 VUs: 97,2 msGameAP 3.x — 1 VUs: 20,2 msGameAP 3.x — 10 VUs: 9,24 msGameAP 3.x — 100 VUs: 8,78 msGameAP 3.x — 800 VUs: 27,7 msGameAP 3.x — 1000 VUs: 1 481 msGameAP 3.x — 1200 VUs: 1 958 msPterodactyl — 1 VUs: 26,9 msPterodactyl — 10 VUs: 12,7 msPterodactyl — 100 VUs: 20,7 msPterodactyl — 800 VUs: 1 144 msPterodactyl — 1000 VUs: 7 664 msPterodactyl — 1200 VUs: 10 455 msPelican — 1 VUs: 29,0 msPelican — 10 VUs: 16,0 msPelican — 100 VUs: 54,5 msPelican — 800 VUs: 1 520 msPelican — 1000 VUs: 10 501 msPelican — 1200 VUs: 12 807 msPelicanPterodactylGameAP 3.xPufferPanelGameAP 4.x

Latencia mediana, ms:

PerfilGameAP 4.xPufferPanelGameAP 3.xPterodactylPelican
smoke (1 VU)1,112,0120,226,929,0
baseline (10 VUs)0,821,549,2412,716,0
load (hasta 100 VUs)0,591,378,7820,754,5
stress (hasta 800 VUs)0,571,4527,71 1441 520
stress-10000,761141 4817 66410 501
stress-120024,697,21 95810 45512 807

Percentil 95, ms:

PerfilGameAP 4.xPufferPanelGameAP 3.xPterodactylPelican
smoke (1 VU)1,694,9829,287,0106
baseline (10 VUs)1,452,0819,979,497,0
load (hasta 100 VUs)1,201,8513,2154473
stress (hasta 800 VUs)2,9258,29089 14611 221
stress-100015,23191 58313 60715 247
stress-12002833302 07814 14417 477

Qué muestra esto.

Hasta 100 VUs inclusive, los cinco paneles responden sin un solo error, y la única cuestión es la velocidad: los paneles Go se mantienen dentro de los 2 ms de mediana, GameAP 3 en torno a 9 ms, Pterodactyl 13–21 ms, Pelican 16–55 ms. La mediana de Pelican ya sube en el perfil load (54,5 ms, p95 — 473 ms): como mostrará la sección de recursos, a 100 VUs prácticamente se ha quedado sin CPU.

En los perfiles de estrés los grupos divergen radicalmente. GameAP 4 supera 800 y 1000 VUs sin degradación de la mediana (0,6–0,8 ms), PufferPanel se ralentiza hasta 114 ms a 1000 VUs y empieza a devolver errores, GameAP 3 aguanta 800 VUs con una mediana de 28 ms (p95 — 0,9 s) y pasa a 1,5–2 s por encima de 1000. Pterodactyl y Pelican ya responden en segundos a 800 VUs, y en 8–13 s (mediana) a 1000–1200.

Obsérvese la brecha entre la mediana y el p95 en los paneles PHP incluso a baja carga: la mediana de baseline de Pterodactyl es 12,7 ms mientras que su p95 es 79 ms. Su cola de respuestas lentas es larga incluso allí donde el panel en conjunto da la talla.

Techo de rendimiento #

El perfil max-throughput: 100 VUs ejecutan las mismas tres peticiones sin pausas — una rampa de subida de 30 s, 2 min de mantenimiento, una rampa de bajada de 10 s. El RPS se calcula como la media de toda la ventana, rampas incluidas.

Techo de rendimiento (max-throughput)cuanto mayor, mejorpeticiones por segundo · 100 VUs, sin think-time · mediana de tres ejecuciones · 0% de errores en todos los paneles02505007501 0001 250GameAP 4.xGameAP 4.x: 1 126 peticiones/s1 126PufferPanelPufferPanel: 696 peticiones/s696GameAP 3.xGameAP 3.x: 394 peticiones/s394PterodactylPterodactyl: 93 peticiones/s93PelicanPelican: 76 peticiones/s76
PanelRPSMedia, msMediana, msp95, msErrores
GameAP 4.x1 12677,668,91790
PufferPanel6961261212570
GameAP 3.x3942222413020
Pterodactyl939417661 8250
Pelican761 1609452 2910

Ningún panel devolvió un solo error, y sin embargo el rendimiento de los extremos difiere 15 veces (1126 frente a 76 peticiones/s). Conviene contrastarlo con la utilización de CPU: en este perfil cada panel funciona a su límite (95–100 % de la CPU de la VM — véase la tabla de recursos). Misma utilización, resultados separados por múltiplos: comparar paneles por «carga de CPU» carece de sentido; lo que importa es cuánto trabajo realiza un panel por núcleo.

Comportamiento bajo sobrecarga #

Peticiones fallidas en los perfiles de estréscuanto menor, mejor% de todas las peticiones (HTTP ≥ 400) · mediana de tres ejecuciones0%10%20%30%40%PufferPanel — 800 VUs: 0,09%800 VUsPufferPanel — 1000 VUs: 21,3%1000 VUsGameAP 4.x — 1200 VUs: 15,2%PufferPanel — 1200 VUs: 34,6%1200 VUs00,09000< 0,0121,300015,234,6000GameAP 4.xPufferPanelGameAP 3.xPterodactylPelican

Peticiones fallidas (HTTP ≥ 400), % de todas las peticiones del perfil:

PerfilGameAP 4.xPufferPanelGameAP 3.xPterodactylPelican
load (hasta 100 VUs)00000
stress (hasta 800 VUs)00,09000
stress-1000< 0,0121,3000
stress-120015,234,6000

Los puntos de ruptura, según estos datos. PufferPanel es el primero en devolver errores: aislados (0,08–0,12 %) ya a 800 VUs, 21 % a 1000, 35 % a 1200 (hasta 40 % en la petición de lista). GameAP 4 supera 1000 VUs casi limpio (mediana: cero errores; 0,011 % en una de las tres ejecuciones) y devuelve 14,3–15,5 % de errores a 1200 VUs. Los paneles PHP no devuelven errores en absoluto, en ningún perfil.

Pero «0 % de errores» aquí no significa «el panel funciona». En stress-1200, el p95 de GameAP 3 es 2,1 s, el de Pterodactyl es 14,1 s, el de Pelican es 17,5 s. Formalmente cada petición termina recibiendo un 200 (k6 espera hasta 60 s); en la práctica, un panel que responde en 10–17 segundos es inutilizable. Son dos modos de degradación distintos, no «PHP aguanta y Go no»:

  • Los paneles Go — fail fast: una parte de las peticiones termina rápidamente en error, el resto se sirve con latencia aceptable (la mediana de GameAP 4 a 1200 VUs es 25 ms, la de PufferPanel es 97 ms). El cliente sabe de inmediato que el servidor está sufriendo.
  • Los paneles PHP — una cola: PHP-FPM encola las peticiones, no hay errores, pero el tiempo de respuesta crece sin límite. El cliente espera sin saber si llegará una respuesta.

Qué modo es el «correcto» es una cuestión de requisitos, no de benchmark. La consecuencia práctica es única: la sobrecarga de un panel PHP no aparecerá en la monitorización de errores, solo en la latencia.

RPS alcanzados en los perfiles de estrés:

PerfilGameAP 4.xPufferPanelGameAP 3.xPterodactylPelican
stress (hasta 800 VUs)2592572108268
stress-10007166153419073
stress-12007646993499074

Léase esta tabla con atención: debido a las pausas de think-time y a la rampa gradual de VUs, el perfil de estrés físicamente no puede entregar más de ~260 peticiones/s (el número medio temporal de VUs activos es ≈ 268, con ~3,1 s de pausas por iteración de tres peticiones). GameAP 4 y PufferPanel alcanzan el techo del perfil, no el suyo propio: 259 y 257. GameAP 3 logra 210. Pterodactyl y Pelican, en cambio, entregan aproximadamente su max-throughput en cada perfil de estrés (82–90 y 68–74 peticiones/s frente a techos de 93 y 76): el panel sirve lo que puede, el resto se acumula en la cola.

Recursos y cuellos de botella #

CPU pico de la VM del panel, %:

PerfilGameAP 4.xPufferPanelGameAP 3.xPterodactylPelican
smoke (1 VU)0,40,63,22,32,9
baseline (10 VUs)0,70,94,88,910,9
load (hasta 100 VUs)2,43,825,781,296,8
stress (hasta 800 VUs)20,465,3100100100
stress-100040,095,6100100100
stress-120087,796,1100100100
max-throughput96,195,3100100100

La fila clave es load: la carga «de trabajo» de 100 usuarios concurrentes, que todos los paneles superan con cero errores, cuesta a GameAP 4 y PufferPanel un 2–4 % de CPU, a GameAP 3 un 26 %, a Pterodactyl un 81 % y a Pelican un 97 %. Pterodactyl y Pelican ya funcionan al borde de la saturación en este perfil: no les queda margen para picos.

A dónde va la CPU bajo sobrecarga: procesos en el perfil de estrés (800 VUs), pico en la ventana, media de las ejecuciones 2–3:

CPU por proceso en el perfil de estrés (800 VUs)cuanto menor, mejorpico en la ventana del perfil · 400% = 4 vCPU · media de las ejecuciones 2–30%100%200%300%400%GameAP 4.xGameAP 4.x — gameap: 31,5% CPU31,5GameAP 4.x — postgresql: 2,9% CPU2,9PufferPanelPufferPanel — pufferpanel: 73,1% CPU73,1PufferPanel — postgresql: 9,5% CPU9,5GameAP 3.xGameAP 3.x — php-fpm: 318% CPU318GameAP 3.x — mysqld: 31,4% CPU31,4PterodactylPterodactyl — php-fpm: 243% CPU243Pterodactyl — mysqld: 109% CPU109PelicanPelican — php-fpm: 260% CPU260Pelican — mysqld: 94,3% CPU94,3aplicación (Go / php-fpm)base de datos (PostgreSQL / MySQL)
ProcesoGameAP 4.xPufferPanelGameAP 3.xPterodactylPelican
Aplicación (Go / php-fpm)31,573,1318243260
Base de datos (PostgreSQL / MySQL)2,99,531,410994,3

100 % = un núcleo, 4 vCPU en total. Nginx se mantuvo ≤ 3,2 % en cada ejecución; Redis, donde process_exporter lo vio, ≤ 5,1 % (la cobertura de monitorización del proceso de Redis resultó incompleta: en algunas ejecuciones process_exporter no lo rastreó; no cambia el panorama, pero se deja fuera de la tabla).

La fila más interesante es la de la base de datos. En Pterodactyl y Pelican, MySQL consume 94–109 % de CPU — casi un núcleo completo — mientras sirve 68–82 peticiones por segundo. En GameAP 3, el mismo MySQL 8.0 con los mismos ajustes está ocupado un 31 %, a 210 peticiones por segundo. Por petición, Pterodactyl y Pelican queman aproximadamente nueve veces más tiempo de CPU de base de datos que GameAP 3. Al parecer, el cuello de botella de estos paneles no es PHP como tal, sino su carga de trabajo de base de datos. La causa no se perfiló y sigue siendo una cuestión abierta; un pase de EXPLAIN sobre las consultas de los endpoints de lista se sugiere por sí mismo.

RAM pico de la VM, MB:

PerfilGameAP 4.xPufferPanelGameAP 3.xPterodactylPelican
smoke (1 VU)4494621 0491 0961 177
stress (hasta 800 VUs)4805391 2881 4631 606
stress-12007017441 3541 4691 610
max-throughput6416721 3421 4451 556

RSS de procesos en stress-800 (media de las ejecuciones 2–3): la aplicación — 65 MB para GameAP 4 y 107 MB para PufferPanel frente a 2,7–4,2 GB de RSS total entre cincuenta workers de php-fpm; la base de datos — 107 MB de PostgreSQL en GameAP 4 frente a ~613–641 MB de MySQL. Dos salvedades: el RSS de los workers de php-fpm cuenta la memoria compartida muchas veces (el consumo real de la VM está en la tabla anterior), y el RSS de PostgreSQL de PufferPanel varió notablemente entre ejecuciones (721 MB en la primera, ~440 MB en la segunda y la tercera).

Y una anomalía que honestamente sigue sin explicación: PufferPanel es el único panel que escribe activamente en disco bajo carga — picos de 140–150 IOPS de escritura frente a 4 de GameAP 4 y 21–24 del resto. La causa (¿logs? ¿auditoría? ¿particularidades del uso de PostgreSQL?) no se investigó.

Lo que muestran los endpoints individuales #

Latencia mediana por endpoint en el perfil load, ms:

EndpointGameAP 4.xPufferPanelGameAP 3.xPterodactylPelican
list_servers0,871,4111,187,3141
server_details0,580,748,3412,725,6
server_status0,381,498,3411,520,9

La lista de servidores es la petición más pesada en todos los paneles, pero en Pterodactyl y Pelican la brecha es dramática: la lista es 7–8 veces más lenta que la petición de detalles (87 y 141 ms frente a 13 y 26 ms). Es la petición de lista la que se degrada primero bajo carga.

Un recordatorio de la salvedad de la metodología: el tamaño de la respuesta de lista difiere entre paneles (102 registros para GameAP, 50 para Pterodactyl/Pelican, 20 para PufferPanel), así que comparar la fila de list_servers entre paneles no es justo. Lo que sí puede leerse de esta tabla es la proporción entre endpoints dentro de un mismo panel, y el hecho de que GameAP 4 devuelve su lista completa de 102 registros (~13 KB) más rápido que cualquier panel PHP devuelve su primera página.

Las tres comparaciones directas #

GameAP 3 → GameAP 4. Para esto fue la reescritura: la mediana de baseline es 9,24 frente a 0,82 ms (11×), la mediana de load es 8,78 frente a 0,59 ms (15×), el techo de rendimiento es 394 frente a 1126 peticiones/s (2,9×), la memoria de toda la VM es 1,0–1,4 GB frente a 0,45–0,70 GB, la CPU en el perfil load es 26 % frente a 2,4 %.

GameAP 4 vs PufferPanel. Ambos son Go + PostgreSQL, y ambos son un orden de magnitud más rápidos que el grupo PHP. Entre los dos: GameAP 4 es 1,9–2,3× más rápido por mediana en baseline/load y 1,6× por el techo de rendimiento (1126 frente a 696), se rompe más tarde bajo sobrecarga (15 % de errores a 1200 VUs frente al 21 % de PufferPanel ya a 1000 y los primeros errores aislados a 800) y apenas toca el disco. Téngase en cuenta, sin embargo, que en este escenario PufferPanel devuelve un orden de magnitud menos datos por petición de lista (20 registros, ~1,6 KB frente a 102 registros, ~13 KB): la brecha se midió sobre un trabajo más ligero para PufferPanel.

Pterodactyl vs Pelican. El fork resultó más lento que el original en todos los perfiles: en load la mediana es 54,5 frente a 20,7 ms, p95 — 473 frente a 154 ms, el techo — 76 frente a 93 peticiones/s, y la saturación de CPU llega antes (97 % ya en load frente a 81 %). Por procesos, el php-fpm de Pelican está más ocupado (260 frente a 243 %) y su MySQL menos (94 frente a 109 %). Las causas de las diferencias no se investigaron; en el momento de la prueba Pelican era un fork joven (1.0.x), y su perfil de rendimiento aún puede cambiar.

Limitaciones #

Una lista de lo que limita las conclusiones de esta prueba.

  1. Bases de datos distintas entre los grupos. Los paneles Go funcionaron sobre PostgreSQL, los paneles PHP sobre MySQL 8.0 (en ambos casos, las configuraciones recomendadas por los desarrolladores de los paneles). Cualquier comparación «Go vs PHP» aquí significa en realidad «Go+PostgreSQL vs PHP+MySQL»: esta prueba no separa la contribución de la base de datos de la del lenguaje y la arquitectura. Dentro de cada grupo las bases de datos son idénticas.
  2. Tamaños de respuesta de list_servers distintos. Cada base de datos contiene 100 servidores, pero GameAP devuelve la lista completa (102 registros), Pterodactyl/Pelican la primera página de 50, PufferPanel la primera página de 20; los tamaños de respuesta van de 1,6 a 16 KB. La prueba no normalizó la paginación a un tamaño de página común. Las comparaciones directas de latencia de lista entre paneles están, por tanto, sesgadas; a favor de quién depende del par (el sesgo aligera el trabajo de PufferPanel y lo hace más pesado para GameAP).
  3. GameAP 3 no tiene endpoint de estado: su server_status es una repetición de la petición de detalles, así que un tercio del escenario en GameAP 3 no es equivalente al de los demás paneles.
  4. Solo lectura, solo API. Sin escrituras, sin WebSocket, sin UI; los servidores ficticios nunca se instalaron ni se iniciaron, y los daemons de las VM vecinas estuvieron prácticamente ociosos. Es una prueba de la capa HTTP/API de los paneles, no de los paneles en su conjunto.
  5. El modelo de bucle cerrado de k6 (véase la metodología): los paneles degradados recibieron automáticamente menos carga, así que sus cifras de estrés son una estimación optimista. El tiempo de espera de petición de k6 es de 60 s.
  6. Calentamiento. Una ejecución de calentamiento smoke (30 s) antes de la serie de perfiles, y un reinicio de servicios antes de cada perfil. En los paneles que no están limitados por CPU (GameAP 3/4, PufferPanel), la latencia media en baseline es mayor que en el perfil load, más pesado (0,85 → 0,66 ms; 1,49 → 1,27; 10,9 → 9,7): parte de la ventana de baseline aparentemente sigue siendo calentamiento. No cambia las conclusiones, pero las cifras absolutas de baseline están ligeramente infladas.
  7. Asimetría de reinicio. Antes de cada perfil, a los paneles PHP se les reinició php-fpm, nginx y MySQL (buffer pool y cachés vaciados; en GameAP 3 también Redis), a PufferPanel se le reinició la aplicación (PostgreSQL siguió en marcha), y a GameAP 4 solo se le reinició nginx (la aplicación y PostgreSQL no). Los paneles PHP empezaron cada perfil «más fríos». Las fases de rampa de los perfiles compensan esto parcialmente, pero la asimetría no se eliminó por completo.
  8. Versiones registradas a nivel mayor (GameAP 4.x / 3.x, Pterodactyl 1.11.x, Pelican 1.0.x, PufferPanel 3.x, abril de 2026). GameAP 4 es funcionalmente más joven y más simple que el resto: hacer menos trabajo por petición puede ser parte de su ventaja; eso no se cuantificó.
  9. Límites modificados. En Pterodactyl y Pelican, los límites de tasa se elevaron a 10 000 peticiones/min; una instalación estándar habría cortado la carga antes.
  10. Monitorización. CPU y RAM son métricas de toda la VM con paso de 15 s (los picos cortos pueden suavizarse); las métricas de procesos tienen paso de 30 s, y la cobertura del proceso de Redis entre ejecuciones es incompleta; las estadísticas de smoke de PufferPanel incluyen la petición OAuth de setup(). Una configuración de hardware, una disposición de VM, 100 servidores en la base de datos: con otro hardware y otros volúmenes de datos, las cifras absolutas diferirán.

Conclusiones #

Volvamos a las tres preguntas de los objetivos.

¿Cuánto difieren los paneles con carga normal? En el perfil load (hasta 100 usuarios concurrentes), los cinco paneles funcionan con cero errores, y la latencia difiere en un orden de magnitud o más: 0,6–1,4 ms de mediana para los paneles Go, ~9 ms para GameAP 3, 21–55 ms para Pterodactyl/Pelican. Dicho sin rodeos: para una persona en un navegador, incluso 55 ms es rápido. Si usted opera un panel, una docena de servidores y ninguna automatización, cualquiera de los contendientes parecerá instantáneo. La diferencia se vuelve práctica con integraciones y automatización, con operaciones masivas, en hardware barato, y en el precio de esa velocidad: los mismos 100 VUs cuestan a Pelican un 97 % de CPU y a GameAP 4, un 2,4 %.

¿Dónde está el punto de ruptura y cómo se rompe un panel? Por techo de rendimiento: 1126 (GameAP 4) → 696 (PufferPanel) → 394 (GameAP 3) → 93 (Pterodactyl) → 76 (Pelican) peticiones/s. Bajo sobrecarga hay dos modos: los paneles Go fallan rápido con errores (PufferPanel desde 800–1000 VUs, GameAP 4 desde 1200), los paneles PHP no devuelven errores pero responden en segundos o decenas de segundos. La conclusión práctica para la monitorización: la sobrecarga de un panel PHP solo es visible en la latencia; no habrá alertas de errores.

¿Cuál es el cuello de botella? Para GameAP 4, la propia CPU de la aplicación (la base de datos apenas está cargada). Para PufferPanel, la aplicación más escrituras de disco notables cuya causa no se investigó. Para GameAP 3, php-fpm (318 % de CPU con MySQL al 31 %). Para Pterodactyl y Pelican el panorama es distinto: junto a php-fpm, MySQL consume casi un núcleo completo; por petición, eso es aproximadamente nueve veces más tiempo de CPU de base de datos del que GameAP 3 gasta en el mismo MySQL. Este es el resultado más interesante de la prueba, y merece una investigación aparte con perfilado de consultas.

Esta prueba mide un solo corte: la velocidad de lectura de la capa HTTP/API. No dice nada sobre funcionalidades, usabilidad, seguridad o ecosistema, y la elección de un panel también depende de eso. GameAP 4 ganó este benchmark, pero también es el contendiente más joven; Pterodactyl perdió en las cifras, y sin embargo sigue siendo el panel más extendido y con el mayor ecosistema. Qué hacer con estos hechos es decisión suya.

Qué sigue #

  • Fase 2 — gestión de servidores de juegos: arranque/parada masivo de N servidores, estado estacionario con servidores en ejecución, consolas WebSocket en paralelo, creación de servidores vía la API. Para ello se está preparando un fake-game-server: un binario que imita a un servidor de juegos real.
  • Escalado por volumen de datos: ejecuciones con 1 / 100 / 1000 servidores en la base de datos, para medir cómo depende la latencia de los endpoints de lista del tamaño de la base de datos.
  • Cuestiones abiertas de esta fase: las escrituras de disco de PufferPanel, el perfilado de las consultas MySQL de Pterodactyl/Pelican, la diferencia entre Pelican y Pterodactyl.

Los scripts, las configuraciones y los datos sin procesar de todas las ejecuciones están en el repositorio game-panels-benchmark. Si encuentra un fallo en la metodología o en la interpretación, abra un issue: se volverá a comprobar y se publicará una corrección.