Guía práctica para dimensionamiento de VPS y tuning de PHP‑FPM para tiendas Magento/OpenMage con picos estacionales: del dimensionamiento a la prueba de carga
Por Kevin Marcondes · Publicado el · 8 min de lectura
Guía práctica para dimensionamiento de VPS y tuning de PHP‑FPM en tiendas Magento/OpenMage con picos estacionales: convierte previsiones de tráfico en capacidad, calcula workers y prepara cache y runtime. El objetivo es mantener baja latencia incluso ante cache miss. Sales con criterios objetivos, ejemplos de configuración y validaciones para ejecutar antes de la campaña.
Qué cambia en picos estacionales en Magento/OpenMage
Los picos estacionales amplifican los cuellos de botella por CPU por núcleo, RAM e I/O, y sacan a la luz las colas del PHP‑FPM. La meta es mantener baja latencia aun cuando falle el cache.
En Magento/OpenMage, la ruta caliente suele ser Nginx/Apache → PHP‑FPM → Redis (sesión/cache) → MySQL. Cuando baja la tasa de aciertos del cache, aumenta la concurrencia dinámica y el consumo de memoria por proceso.
Planifica capacidad para el peor caso razonable (miss parcial del cache), con un dimensionamiento realista, parámetros coherentes del FPM y caminos de degradación controlados.
Cómo estimar el tráfico de pico estacional?
La estimación empieza con RPS (peticiones por segundo) y se convierte en concurrencia en el PHP‑FPM. Enfócate en las rutas críticas y en el mix de tráfico anónimo vs. autenticado.
Relaciona la tasa de aciertos del cache, el coste medio de la petición dinámica y el tiempo de respuesta objetivo. Esas variables definen la concurrencia necesaria en el pool del FPM.
- Recolecta RPS histórico por minuto en eventos anteriores.
- Estima el hit ratio del cache por tipo de página (home, PLP, PDP, checkout).
- Mide el tiempo medio de respuesta dinámico bajo carga (p95).
- Concurrencia objetivo ≈ RPS_dinámico × tiempo_medio_respuesta.
- Incluye picos relámpago de campañas (ej.: 2× en 10 min).
- Añade margen para jobs de Magento (consumers, indexers) en la ventana.
¿Cuántos workers de PHP‑FPM necesito?
El número de workers depende de la memoria por proceso y de la concurrencia deseada. Usa una fórmula simple y luego valida con pruebas de carga representativas.
Mide la memoria media por child en producción/staging (ps/top + pm.status) durante tráfico real. A partir de ahí, calcula pm.max_children y ajústalo con observabilidad.
- Memoria disponible para PHP = RAM_total − SO − servicios (Redis/MySQL/nginx).
- Memoria por child = pico observado bajo carga + margen.
- pm.max_children ≈ floor(Mem_PHP / Mem_por_child).
- pm = dynamic para mantener procesos calientes en el pico.
- pm.max_requests para reciclar asignaciones y contener fugas.
- Ajusta start/min/max_spare para evitar una tormenta de forks.
; Exemplo inicial de pool (ajuste aos seus números)
[www]
pm = dynamic
pm.max_children = 120
pm.start_servers = 16
pm.min_spare_servers = 16
pm.max_spare_servers = 32
pm.max_requests = 1000
request_terminate_timeout = 60s
request_slowlog_timeout = 2s
slowlog = /var/log/php-fpm/www-slow.log
pm.status_path = /status
ping.path = /ping
ping.response = pong
Elección de VPS: CPU, RAM, I/O y red
El rendimiento por núcleo pesa más que el recuento de vCPUs. Prefiere NVMe consistente, vCPU dedicadas cuando sea posible y monitorea el steal time de la CPU.
I/O estable y latencia de red predecible evitan colas largas. Ajusta la memoria dedicada a PHP según Redis, MySQL y el servidor web presentes en el host.
| Perfil de pico | vCPU | RAM para PHP | Disco/IOPS | Observaciones |
|---|---|---|---|---|
| Bajo (hasta 2k RPS cacheado) | 2–4 | 4–8 GB | NVMe básico | Enfócate en cache y opcache caliente. |
| Medio (cache medio, miss relevante) | 4–8 | 8–16 GB | NVMe estable | Equilibra children con memoria por proceso. |
| Alto (promociones intensas) | 8–16 | 16–32 GB | NVMe priorizado | Separa web y cola, y considera escala horizontal. |
Cache de página, bloques y sesiones para absorber ráfagas
El cache reduce el trabajo del PHP en los picos. Combina cache de página completa, cache de bloques y sesión externa para permitir escala horizontal sin sticky sessions.
Aumenta la tasa de aciertos con TTLs por ruta, invalidación por evento y compresión. Trata la ruta de usuario anónimo como prioridad y protege el checkout con cache selectivo de bloques.
- Página completa con proxy de borde o Varnish.
- Bloques dinámicos vía ESI/holes cuando esté soportado.
- Sesiones y page cache en Redis separados de las colas.
- Headers correctos para variar por device/región.
- Compresión gzip/brotli cuando aplique.
- Monitorea hit ratio por ruta y por tipo de usuario.
Cómo preparar PHP‑FPM para ráfagas en fechas especiales?
Preparar el runtime reduce las colas largas de latencia. Haz warm‑up del opcache, ajusta límites de ficheros y habilita slowlog para cazar N+1 y consultas lentas.
Revisa el backlog del servidor web, las conexiones a Redis/MySQL y los timeouts del gateway. Pequeños ajustes evitan cascadas cuando hay miss parcial del cache.
- Warming del opcache tras deploy para no compilar bajo pico.
- realpath_cache_size y TTL coherentes con Magento/OpenMage.
- rlimit_files/ulimit para evitar “Too many open files”.
- request_terminate_timeout para bloqueos ocasionales.
- emergency_restart_threshold/interval para stucks raros.
- Backlog del listener alineado con el front (net.core.somaxconn).
- Healthchecks y status paths expuestos y protegidos.
; opcache (ajuste conforme seu código e catálogos)
[opcache]
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=65407
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.save_comments=1
opcache.jit=0
Escalar horizontalmente con seguridad y sin sticky sessions
La escala horizontal exige instancias web stateless. Guarda sesiones y cache fuera del nodo y trata los assets compartidos para poder subir y bajar nodos en el pico.
Implementa health checks y readiness para sacar nodos del balanceador sin derribar sesiones. Planifica deploys sin impacto durante la ventana crítica.
- Sesiones en Redis y sin sticky sessions en el balanceador.
- Media en object storage o NFS robusto.
- Consumers/indexers en nodos separados con límites claros.
- Readiness y liveness en el web para evitar tráfico a nodos fríos.
- Blue/green o canario fuera de ventanas críticas.
Cómo validar el sizing antes del Black Friday?
Valida la capacidad con pruebas de carga que simulen el mix real y fallos parciales del cache. Reproduce picos relámpago y anomalías de tráfico para reducir sorpresas.
Mide p95/p99 por ruta, saturación de CPU, colas del PHP‑FPM y steal time. Ajusta parámetros, repite y congela las configuraciones tras alcanzar las metas.
- Escenarios: anónimo con cache, autenticado sin cache y checkout.
- Scripts k6 con etapas y picos de corta duración.
- Monitorización: pm.status, slowlog y tiempos de query en la BD.
- Criterios de éxito con error budget y latencia objetivo.
- Prueba de rollback de deploy y de feature flags.
- Concurrencia estimada validada en prueba de carga.
- pm.max_children calculado por uso real de memoria.
- pm.status, ping y slowlog habilitados y protegidos.
- Opcache precalentado y parámetros ajustados al código.
- Redis separado para sesión y page cache.
- Backlog del web y del FPM coherentes con el tráfico.
- Límites de ficheros ajustados en el SO y en el FPM.
- Playbook de escala horizontal probado.
- Alertas de p95/p99 y cola del FPM configuradas.
- Plan de rollback de deploy listo.
Preguntas frecuentes
¿Cuál es la fórmula práctica para definir pm.max_children?
La fórmula es: pm.max_children ≈ floor(Memoria_disponible_para_PHP ÷ Memoria_por_child). Mide la memoria por child bajo carga con ps/pm.status. Incluye margen para picos cortos y otros servicios en el host, y valida con pruebas de carga.
¿Debo usar pm=dynamic o pm=ondemand para Magento/OpenMage?
Para picos previsibles, pm=dynamic mantiene procesos calientes y reduce la cola de latencia. pm=ondemand ahorra RAM en off‑peak, pero puede aumentar latencia al crear procesos. En campañas, prefiere dynamic o precalienta ondemand.
¿PHP 8 JIT ayuda en Magento/OpenMage?
En general, JIT aporta poco beneficio para aplicaciones web I/O‑bound como Magento/OpenMage. Prioriza opcache, consultas y tuning del FPM. Prueba en staging con tu carga antes de habilitar JIT en producción.
¿Necesito Varnish para aguantar picos?
No es obligatorio, pero un proxy de cache de página incrementa mucho la capacidad. Combínalo con invalidación correcta y sesiones en Redis para descargar el PHP‑FPM. Sin cache, el dimensionamiento de CPU/RAM debe ser mayor para soportar miss.
¿Puedo usar el mismo Redis para sesión y cache de página?
Lo ideal es separar instancias o al menos bases y políticas de eviction. Las sesiones no deben competir con claves de página. Define TTLs, tamaños y eviction coherentes para cada propósito.
¿Cuándo escalar verticalmente y cuándo horizontalmente?
Escala vertical mientras haya ganancias claras con más CPU/RAM y menor coste. Escala horizontal cuando se alcancen límites de núcleo único, I/O o cuando necesites aislar riesgos y mantener deploys sin downtime.
¿Quieres revisar sizing y tuning antes de la próxima campaña?
Si necesitas validar capacidad, ajustar PHP‑FPM y preparar una escala segura para Magento/OpenMage, hablemos de un plan objetivo y testeable.
Solicitar una conversación técnicaVer también
- Guía práctica: configurar failover activo‑pasivo entre dos VPS con Keepalived, HAProxy y lsyncd para uploads sincronizados
- Guía: checklist técnico para preparar un VPS Debian con Docker Compose para aplicaciones PHP en producción
- Guía: cómo planificar y ejecutar pruebas de carga en aplicaciones PHP monolito usando k6 y Docker Compose — paso a paso
- Guía de backup y recuperación PostgreSQL con wal‑shipping y basebackup en VPS con espacio limitado: práctica de bajo uso de disco