14 puntos por GN⁺ 2025-09-02 | 5 comentarios | Compartir por WhatsApp
  • Recientemente ha cobrado atención un enfoque híbrido que integra Go y Rust como lenguajes de extensión dentro de una arquitectura monolítica de PHP
  • Antes, la combinación de microservicios en Go y un monolito en PHP 8.3 permitía lograr un equilibrio entre productividad y alto rendimiento
  • Siguiendo la ley de Pareto (80% del tráfico concentrado en el 20% de las API), era indispensable optimizar los endpoints críticos; antes se respondía con caché y separación de servicios en Go, pero eso aumentaba la complejidad
  • Con la evolución reciente del ecosistema de PHP, han surgido técnicas como FFI, extensiones en Rust y extensiones en Go (FrankenPHP), que permiten elevar drásticamente el rendimiento dentro del propio monolito
  • Las extensiones en Rust ofrecen al mismo tiempo seguridad de memoria y velocidad, y FrankenPHP muestra mejoras de rendimiento de hasta más de 4 veces con su modo worker y extensiones basadas en Go
  • Sin asumir el costo y riesgo de reescribirlo todo en Go o Rust, el enfoque de PHP híbrido permite obtener productividad y velocidad a la vez

Contexto y arquitectura previa

  • Antes, se desarrollaban microservicios basados en Go (children) por separado para optimizar funciones específicas, tomando como eje una aplicación monolítica DDD (mother)
  • Los microservicios en Go se encargaban de manejar tráfico de alto rendimiento, mientras que el monolito en PHP 8.3 ofrecía desarrollo rápido de features y confiabilidad en el despliegue en un entorno con un equipo backend pequeño
  • Esta estructura ofrecía un punto de equilibrio para asegurar velocidad, estabilidad y productividad

Cuellos de botella de rendimiento y formas previas de responder

  • Con frecuencia se observa el principio de Pareto, donde el 80% del tráfico se concentra en el 20% de los endpoints de API
  • Para ese 20% donde el rendimiento es más importante, se adoptaban distintos métodos: escribir código optimizado, agregar una capa de caché o separar microservicios en Go
  • Sin embargo, había límites en términos de complejidad y carga operativa

Opciones híbridas en el ecosistema moderno de PHP

  • En tiempos recientes han aumentado las tecnologías para mejorar directamente el rendimiento dentro del monolito de PHP
  • 1. FFI (Foreign Function Interface)

    • La funcionalidad FFI de PHP permite llamar código C directamente desde PHP
    • Incluso la lógica a nivel de sistema o crítica para el rendimiento puede implementarse dentro del proyecto PHP
    • Aun así, se recomienda usarlo solo en situaciones adecuadas, considerando el costo del cambio de contexto
  • 2. Extensiones basadas en Rust

    • Es posible desarrollar extensiones de PHP con Rust (o Zig)
    • Al descargar las áreas de alta carga a extensiones en Rust, que ofrecen seguridad de memoria y rendimiento compilado, es posible asegurar tanto confiabilidad como alta velocidad
  • 3. Extensiones basadas en Go: FrankenPHP

    • Tras migrar recientemente a FrankenPHP y ejecutarlo en worker mode, se confirmó un rendimiento más de 4 veces más rápido que antes
    • En una versión reciente también se hizo posible escribir extensiones de PHP en Go
    • Con ello, se puede aprovechar el rendimiento de API de Go directamente dentro del monolito PHP y combinar productividad y velocidad sin dividir el sistema por lenguaje

Por qué no hacer una migración completa a Go o Rust

  • El costo de una reescritura total y el riesgo asociado son altos
    • Cambiar por completo una aplicación ya grande y estable a Go o Rust implica mucho riesgo y consumo de recursos
  • PHP todavía conserva fortalezas propias
    • En la mayoría de los trabajos, el desarrollo rápido en PHP, su ecosistema amigable y una velocidad suficientemente buena siguen siendo competitivos
    • Si solo las áreas que realmente necesitan el límite máximo de rendimiento se configuran de forma híbrida con Go o Rust, se puede eliminar la necesidad de una migración completa

Conclusión: el valor del PHP híbrido

  • El ecosistema moderno de PHP ofrece tanto alta productividad de desarrollo como opciones de integración con extensiones de alto rendimiento (C, Rust, Go)
  • Con esta estructura híbrida es posible asegurar tanto velocidad como productividad
  • Se plantea un nuevo paradigma de arquitectura que mantiene el desarrollo centrado en PHP y permite extender selectivamente con otros lenguajes cuando sea necesario

5 comentarios

 
naearu 2025-09-02

Parece que se está volviendo algo parecido a cómo ha ido cambiando JavaScript.

 
skageektp 2025-09-02

Aunque con Node.js y Rust, bueno...;; en mi caso, como en PHP se sigue usando $ y cosas así, siento que debe ser incómodo escribir código. ¿La gente que lo usa bien no suele sentir tanta incomodidad?

 
proinworks 2025-09-03

Aunque se sienta incómodo, ¿no te acostumbras rápido después de usarlo un tiempo?
Los seres humanos somos animales de adaptación.

 
nemorize 2025-09-02

Si algo me resultaba incómodo, era el concepto mismo de variables/funciones en PHP; nunca me ha molestado en absoluto la notación con $.

¿No eran más bien bromas esos comentarios de que no se puede usar por culpa del signo de dólar, ~~que los que usan el signo de dólar ganan mucho dinero, que no es dólar estadounidense sino dólar zimbabuense y por eso no ganan tanto~~...?

 
GN⁺ 2025-09-02
Opiniones de Hacker News
  • Cada vez le agarro más rechazo a los frameworks de propósito general (Spring, Laravel, Phoenix, etc.); al principio son realmente productivos, pero en proyectos legacy siempre se repiten los mismos problemas. Como cada proyecto tiene una infraestructura o condiciones de negocio distintas, no se puede hacer todo solo siguiendo la forma recomendada del framework, así que empiezan a acumularse parches extra y trucos con dependencias por todos lados. Cuando intentas actualizar a un lenguaje o versión nueva, todas esas partes personalizadas se rompen, así que al final nadie actualiza nada hasta que ya no se puede seguir ejecutando en la infraestructura y toca una migración dolorosa entre lágrimas. Armar tus propias abstracciones combinando varias librerías puede tomar más tiempo, pero permite actualizar con flexibilidad por partes y cambiar de rumbo rápido. Por eso empecé a pensar que el ecosistema de Go es ideal en ese sentido; al principio se me hacía raro, pero ahora incluso prefiero más ese enfoque.

    • Con los frameworks web me queda mucho la sensación de que “al principio son buenísimos, pero llega un punto en que se vuelven incómodos”. Cuando haces una app simple, cosas como Rails y eso de “crear un blog en 15 minutos” se sienten casi mágicas, pero cuando la cosa se complica, el framework termina siendo un obstáculo. Personalmente me siento más cómodo con configuraciones HTTP de “nivel intermedio” como Express + Node.js o Vert.x + Java.

    • En Python se puede ver la diferencia entre microframeworks (tipo Flask) y macroframeworks (Django). Yo siempre elijo Django; Flask casi no te propone nada, así que cada proyecto termina siendo un copo de nieve decorado desde cero. Aparece la fatiga de decidir entre N opciones para autenticación, plantillas, cookies, correo, etc. Sobre todo porque muchas de esas librerías suelen ser de un solo desarrollador, así que la calidad de mantenimiento y seguridad varía mucho. En cambio, con Django la mayoría de los proyectos se parecen entre sí y casi todas las funciones básicas vienen listas desde el inicio. Solo veo razón para usar librerías de extensión cuando hay requisitos especiales; como hay muchas más partes mantenidas y validadas directamente, siento que la confiabilidad del código y la seguridad también son mayores.

    • La razón por la que Go no tiene frameworks gigantes es que su sistema de tipos sigue bastante incompleto. Es difícil construir librerías complejas que encajen bien entre sí. Yo esperé 9 años hasta que se pudo usar genéricos para recién entonces hacer mi primer toolkit de base de datos para Go. Fue exitoso, pero aun así sentí que cuando hacía esto mismo en Java era mejor. Si se pudiera hacer map/filter/reduce sobre un tipo resultado hacia otro tipo genérico, sería un mundo completamente distinto. Con solo tener una forma de declarar tipos union, ya no habría necesidad de usar el tipo any. Si al menos hubiera soporte para sobrecarga, el código quedaría muchísimo más limpio; el sistema de tipos de Go todavía necesita evolucionar más.

    • En mi área solo Go y Rust sirven. La cultura de frameworks muy opinionados no me va. Creo que Rails, Laravel y Django son excelentes cuando hay operaciones CRUD sobre una base de datos relacional claramente definidas.

    • En los últimos 5 años solo he usado componentes compatibles con PSR (Php Standards Recommendation); no uso frameworks en absoluto. La razón es que los frameworks grandes terminan dejando de encajar con el tiempo. Tienen demasiadas restricciones, y mantenerlos y actualizarlos se vuelve muy difícil. Ya sea para proyectos corporativos grandes o servicios personales, siento que una arquitectura centrada en componentes PSR funciona mejor.

  • Entiendo que cuando tienes una base de código enorme y es imposible reescribir todo, un enfoque híbrido (usar PHP junto con lenguajes de rendimiento como C, Rust o Go) puede tener sentido. Pero si no hay necesidad de eso, mi experiencia es que una API en C# logra tanto velocidad de desarrollo como rendimiento de ejecución. Casi nunca tuve que llegar a C++ o Rust. PHP también está bien, pero todavía no soporta cosas como arreglos tipados. Por ejemplo, es un lenguaje que no rechaza que una cadena termine en un arreglo de fechas.

    • He usado C# durante mucho tiempo y tengo experiencia con varios frameworks web/API. Si uno profundiza un poco en PHP, está muy bien porque trae muchísimas funciones integradas básicas para desarrollo web. Tiene desventajas, pero cuando hay que hacer algo rápido, en mi opinión PHP gana.

    • Es cierto que PHP permite tipos incorrectos en arreglos, por ejemplo una cadena dentro de un arreglo de fechas. A veces aparecen comportamientos raros o bugs. Hace poco me topé con un bug donde, al decodificar con json_decode(), si la clave era numérica entraba como int y si no como string, así que terminabas con tipos de clave mezclados. Esos rincones pueden ser bastante extraños, pero aun así PHP en sí es de verdad un lenguaje Frankenstein muy atractivo.

    • En la práctica, si usas un analizador estático, ese tipo de errores de tipos se evita. Además, es muy probable que pronto llegue soporte de genéricos a PHP. Se puede ver más sobre eso en el blog de thephp.foundation.

    • Soy quien escribió el artículo, gracias por leerlo. En realidad no hace falta reescribir todo; si ejecutas PHP sobre un runtime basado en workers como swoole o frankenphp, puedes obtener un rendimiento a nivel de Node. Los problemas de arreglos tipados o genéricos también los cubren analizadores estáticos como phpstan, y si aprovechas anotaciones de tipo puedes mejorar bastante la seguridad de tipos.

    • Desde que terminó el soporte de VB6 decidí no volver a usar lenguajes de Microsoft. Solo los lenguajes open source son una elección sana para la salud mental.

  • Cuando entré a {{company}}, toda la empresa estaba en PHP 5.4 y en ese momento sobraban las opiniones negativas sobre PHP. Pero después de probar PHP moderno, justo ahora que ya estamos en la recta final para salir de PHP, esta migración incluso se siente más bien como un retroceso. Todavía hay mucha gente que juzga PHP por la época de 5.x, pero hoy es completamente distinto.

    • Yo lo veo un poco distinto; si miras el mercado laboral, la percepción sobre PHP sigue existiendo (sea buena o mala), y eso limita a la hora de contratar desarrolladores excelentes. Aunque técnicamente PHP ya no sea tan malo como antes, desde el punto de vista de marca empresarial todavía tiene sentido alejarse de PHP.

    • No estoy de acuerdo con eso de que “PHP ahora es awesome”; sin duda mejoró, pero decir awesome ya es exagerar un poco.

    • PHP está mejorando cada vez más; creo que pronto debería revisarlo con más profundidad.

    • Nosotros tuvimos exactamente la misma duda hace 4 años y al final seguimos usando PHP tras actualizar a PHP 8. Esa decisión nos ha funcionado bien al equipo durante estos últimos años.

  • Pasir es parecido a frankenphp, pero está basado en Rust; promete mucho, aunque todavía está en una etapa temprana de desarrollo.

  • Pasir github Pasir usa una conversión a Rust de los bindings de la API de Zend.

  • Bindings Rust de la API de Zend También hay experimentos interesantes como ngx-php, cuya estructura incrusta PHP con la API de Zend dentro del binario de nginx.

  • ngx-php github workerman implementa un runtime muy rápido usando un backend híbrido con asio.

  • workerman github

    • Me pregunto si Pasir, frankenphp y similares también soportan módulos PHP existentes.

    • Gracias por la recomendación, de verdad se ve genial. Pero como dices, coincido en que todavía está lejos de estar listo para producción. Nosotros al final elegimos frankenphp, que está respaldado por php foundation.

  • Muchas veces se pasa por alto la complejidad del debugging y del mantenimiento; si tienes opción, creo que conviene evitar este tipo de combinaciones.

    • Gracias por la opinión; elegimos frankenphp, así que si hay alguna razón por la que el debugging se vuelva más difícil, me gustaría que lo explicaras con más detalle.
  • Yo también reescribí mi app de PHP a Go, y para la empresa fue una inversión exitosa. Pude reducir 20 mil líneas de PHP a 4 mil líneas de Go y mejorar muchísimo la eficiencia. Si tu empresa es de PHP, recomendaría seriamente planear una reescritura grande y hacerla junto con agregar pruebas (que en Go es más fácil). Me parece mejor eso que sufrir el dolor de mantenimiento de mezclar varios lenguajes como Rust/PHP o Go/PHP.

    • Me intriga cómo fue posible reducir tanto la cantidad de líneas al migrar de PHP a Go. Go me parece un lenguaje bastante verboso; en mi experiencia, PHP queda en un punto medio, Haskell es el más compacto, y Java/Go tienden a alargarse más por cosas como el manejo de errores.

    • No me convence eso de que al pasar de PHP a Go se haya reducido el código 5 veces. Siento que PHP tiene muchas sintaxis abreviadas, mientras que Go no tanto.

    • Creo que siempre es importante preguntarse si la mejora en rendimiento y eficiencia tras una reescritura se debe “al lenguaje” o a mejoras de arquitectura que se introdujeron al rehacer el sistema.

    • Yo pensaba que al reescribir en Go el patrón if err != nil iba a inflar el código 10 veces. Pasé por una reescritura en Python, y Python también se vuelve bastante verboso; además, patrones como la inyección de dependencias se vuelven molestos en testing.

    • No recomiendo reescribir a ciegas (aunque yo mismo completé dos reescrituras con éxito, igual probablemente no la elegiría por voluntad propia). Los runtimes modernos de PHP se han vuelto realmente rápidos, así que vale la pena probarlos. Sobre todo si aprovechas bien el caché de trabajo de algo como swoole, a veces puede ser tan rápido como Go (recomiendo revisar benchmarks).

  • A veces pienso que de verdad deberíamos volver a lo básico: píxeles, datos, latencia/ancho de banda. La web también es, al final, un problema de optimización para dibujar los píxeles correctos a una velocidad perceptiblemente rápida para el ojo humano, dentro de los recursos de red disponibles. Siento que hay que abordarlo pensando cosas como: “¿Qué píxeles va a ver el usuario enseguida?”, “¿Qué datos hacen falta para dibujarlos?”, “¿Conviene hacer prefetch de datos que probablemente se usarán después?”.

    • Estoy haciendo alumina-ui con egui para WASM, y sin tener que lidiar con conocimientos complejos de HTML, JavaScript o CSS, basta con dar un canvas del tamaño adecuado para el navegador y renderizar directamente con WebGL. Poder sacar gráficos rápidos y acelerados por GL en un lenguaje que me gusta es muy conveniente. WASM/WebGL me encanta justo por ese tipo de abstracción.

    • Enfocarse solo en los píxeles que ve el usuario es una visión demasiado parcial. En proyectos de software no solo hay que optimizar la UX inmediata, también el tiempo de desarrollo. El retraso hasta que aparece la primera pantalla y el tiempo real de desarrollo no guardan una proporción directa en absoluto.

  • FrankenPHP se ve bastante interesante, pero en la práctica es algo raro. Nadie usa PHP sin módulos PHP, y no está claro qué lista de módulos soporta FrankenPHP ni si se pueden compilar y agregar módulos aparte que yo quiera. Está muy acoplado a Caddy, y yo no conozco ese servidor web; prefiero nginx. Como no hay guías, tampoco sé si se puede usar con nginx como reemplazo de php-fpm. Además, las imágenes Docker de Caddy o FrankenPHP parecen pensar solo en certificados de Let's Encrypt, así que si quieres configurar SSL manualmente o correr solo por HTTP, resulta muy poco intuitivo.

    • El tema de los módulos PHP normalmente se resuelve compilándolos directamente dentro del Dockerfile. Por ejemplo, para agregar el módulo pgsql instalas dependencias con apt, instalas el módulo con docker-php-ext-install y al final eliminas/limpias las dependencias. La configuración HTTP también se puede hacer abriendo directamente el puerto 80 en el Caddyfile.

    • El build estático incluye por defecto decenas de módulos principales de PHP. La lista detallada de módulos y el script de build se pueden ver en frankenphp build-static.sh.

  • Me da curiosidad saber para qué tipo de carga de trabajo realmente hacen falta extensiones en lenguajes como C/Rust/Go. Entiendo que existen, pero me gustaría saber más sobre por qué habría que agregar esa complejidad al stack y por qué no se puede resolver de otra forma.

  • Lo que más detesto de PHP es que en cada request HTTP se vuelve a bootstrapping toda la aplicación y se reevalúan el autoloading y la configuración. Claro que hay cachés y demás, pero comparado con algo como Go, donde el motor siempre está corriendo, sigue sin convencerme.

    • En realidad, hay varias librerías bastante bien documentadas que te permiten correr un servidor independiente solo con PHP, y sirven también para producción. El rendimiento del JIT de PHP también es bastante impresionante.
  • reactphp.org

  • php.net ev module

  • pecl-event

  • workerman.net

    • No necesariamente tiene que funcionar así (ejecutarse de nuevo en cada request). Algunos runtimes de PHP soportan que una sola ejecución del script procese múltiples requests HTTP.
  • documentación de frankenphp worker

    • Yo más bien creo que esa es la mejor ventaja de PHP. Hace que escalar horizontalmente sea increíblemente fácil.

    • A mí, al contrario, me gusta esa estructura. Intrínsecamente minimiza el estado (hasta cierto punto).

    • Tienes razón, esa forma es realmente pésima. Sobre todo es más problemática cuando PHP se usa como su propio lenguaje de plantillas. Los motores de plantillas personalizados o los runtimes persistentes que intentan arreglarlo al final no dejan de ser solo “ponerle lápiz labial a un cerdo”. Mejor habría sido elegir desde el principio un lenguaje cuyo nombre no fuera Personal HomePage.