🔧 Programmierung 🕛 vor 3 Monaten 12 Min Lesezeit
0

El benchmark que me hizo cambiar de opinión sobre Jakarta EE en 2026

↗ Quelle (dev.to)
🗣️ Stimme:

La primera tabla me dejó incómodo: en mi máquina, con el workload realista del lab, Embedded GlassFish parecía ganarle a Spring Boot. Si publicaba ahí, el post tenía más punch, pero también era metodológicamente flojo. Paré la pelota y agregué lo que faltaba: JDK soportado para todos, warmup separado, ventanas medidas más largas, heap fijo, pool settings explícitos y pg_stat_statements para atribuir la base. Con eso, la conclusión cambió.



Este post no intenta decidir quién “gana para siempre”. Cuenta cómo cambió mi lectura cuando el benchmark se volvió justo. Y por qué, si hoy arranco un greenfield con un equipo que ya vive en Spring, sigo eligiendo Spring Boot; pero si estoy en una organización con Payara/Jakarta, pruebo Payara Micro; y si hay código Jakarta que busca ejecutable liviano, Embedded GlassFish entra a la conversación.



Por qué hice este experimento




  • Venía con una idea fácil de repetir: “Spring Boot siempre es la opción obvia”. Quería desafiarla con evidencia, no con intuición.

  • Me interesa Jakarta EE moderno sin nostalgia. Quería ver si hay espacio real hoy, no en 2012.

  • Evité el Hello World. Armé una API chica pero realista, DB-heavy, con reads, writes, agregaciones y carga mixta.

  • El objetivo editorial es simple: decidir con mediciones que se puedan defender, no con folklore.



El sistema que implementé



El dominio del lab fue shipment-intelligence, misma API servida en tres runtimes: Spring Boot, Embedded GlassFish y Payara Micro.




  • PostgreSQL con dataset determinístico grande (100k envíos).

  • Tracking read por trackingId.

  • Summaries operativos (ruta y volúmenes).

  • Delayed shipments paginados.

  • Event ingestion real a la base.

  • Health/readiness.

  • k6 como generador de carga con escenarios compartidos.

  • Medición de RSS, GC logs, stdout/stderr de los runtimes y pg_stat_statements para entender el costo de la DB.



No muestro código acá. Todo lo que importa para este post es que las tres versiones implementan el mismo contrato HTTP y apuntan a la misma base, con los mismos escenarios k6.



Cómo cambió la conclusión a medida que mejoré la metodología



El giro narrativo de este lab se explica con dos fotos: Phase 2 y Phase 4. La primera es la tentación de publicar rápido. La segunda es cuando el experimento se vuelve defendible.



Tabla Phase 2 (realistic operational benchmark, 3 corridas por runtime)




































Runtime Median p50 Median p95 Median p99 Median throughput
Embedded GlassFish 4.66 ms 58.77 ms 111.85 ms 86.46 req/s
Payara Micro 16.32 ms 135.76 ms 238.61 ms 71.17 req/s
Spring Boot 36.59 ms 340.50 ms 594.74 ms 53.36 req/s


Lectura honesta de Phase 2: si frenaba ahí, el titular fácil era “GlassFish volvió”. Pero faltaban demasiadas cosas: no había pg_stat_statements, no capturé RSS por corrida, las muestras eran cortas, no separé warmup, el JDK no estaba uniformado y los pools no estaban todos declarados igual. Era una buena base para seguir, no para cerrar el tema.



Phase 3 agregó causalidad y complejidad (VU 10/25/50/100, tres corridas por combinación, DB attribution, RSS before/after, GC logs). GlassFish siguió fuerte en tail latency a VUs altos, Payara peleó throughput, Spring Boot se mantuvo con menor RSS. Pero apareció un warning clave: en algunas corridas Payara reclamaba JDK no soportado. Necesitaba una fase más justa.



Phase 4: el benchmark justo (base del post)



Acá está la foto que me importa para contar la historia. Controles:




  • Temurin 21.0.10 para todos.

  • Heap fijo: -Xms512m -Xmx512m.

  • Warmup separado y ventana medida de 180s.

  • Pool settings explícitos.

  • pg_stat_statements reseteado después del warmup.

  • Tres corridas por runtime/VU, con VUs 25 y 100.



Tabla principal Phase 4




























































































Runtime VUs Runs Median p50 Median p95 Median p99 Median throughput Worst error rate Check failures Median RSS before
Spring Boot 25 3 4.59 ms 66.92 ms 110.03 ms 213.13 req/s 0.01% 2 517.5 MB
Payara Micro 25 3 33.10 ms 188.16 ms 336.77 ms 156.48 req/s 0.00% 0 694.3 MB
Embedded GlassFish 25 3 38.03 ms 198.83 ms 371.96 ms 151.26 req/s 0.00% 0 579.1 MB
Spring Boot 100 3 149.36 ms 341.69 ms 473.41 ms 372.56 req/s 0.04% 25 543.0 MB
Payara Micro 100 3 204.61 ms 588.31 ms 870.53 ms 284.29 req/s 0.00% 0 715.7 MB
Embedded GlassFish 100 3 320.12 ms 540.00 ms 677.23 ms 229.28 req/s 0.01% 5 593.9 MB


Lectura editorial de Phase 4 (acotada a este workload local y a mi máquina):




  • A 25 VUs, Spring Boot quedó claramente adelante en mediana de latencia y throughput, con menor RSS relativo dentro del heap fijo.

  • A 100 VUs, Spring Boot también tuvo mejor p95/p99 y throughput mediano. El costo fue registrar check failures: 25 en el set de 100 VUs y 2 en 25 VUs. No lo escondo porque también habla del sistema bajo presión.

  • Payara Micro fue el Jakarta EE más “limpio” por check failures en Phase 4: 0 a 25 y 0 a 100 VUs. En throughput quedó segundo y con la p50 más baja del grupo Jakarta a 100 VUs, aunque con mayor RSS.

  • Embedded GlassFish siguió siendo viable y técnicamente interesante, pero dejó de liderar cuando el método se volvió más estricto.



Cómo la DB explicó parte de la historia



Con pg_stat_statements quedó claro que este lab es DB-heavy. Las agregaciones analíticas (ruta/volúmenes) dominaron la cola de latencia en presión. El tracking read, en cambio, fue barato. Eso no prueba que la diferencia venga “solo del runtime”. Muestra que la comparación se hace en un sistema donde PostgreSQL, el pool, JDBC, k6 en Docker y el host también cuentan. Es la clase de sintonía fina que quiero ver antes de sacar un titular.



La experiencia de desarrollo (breve y honesta)




  • Spring Boot fue lo más rápido para iterar. No es un mérito absoluto del framework; es la realidad de un equipo chico que ya vive ahí. Config, packaging, health/readiness y observabilidad entraron casi sin pensar.

  • Payara Micro se sintió pragmático si ya existe cultura WAR/Jakarta. En los runs de Phase 4 fue impecable en check failures. Requirió más interpretación de logs y detalles de runtime.

  • Embedded GlassFish fue la sorpresa. Me acercó a un ejecutable Jakarta EE más liviano de lo que esperaba. No ganó la fase final, pero me hizo revisar prejuicios.



Mini mapa de evolución (de “parece que” a “conclusión justa”)




  • Phase 2: GlassFish parecía ganador del workload realista.

  • Phase 3: GlassFish fuerte en tail latency, Spring con menor RSS, Payara competitivo; JDK de Payara no soportado en parte de las corridas.

  • Phase 4: con Temurin 21, heap fijo, warmup y ventanas largas, Spring Boot quedó con el mejor perfil local de latencia/throughput; Payara Micro sin check failures fue el Jakarta EE más limpio; GlassFish siguió viable.

  • Phase 5: smoke externo en Railway, útil para portabilidad, no para performance.



Railway como smoke, no como podio



El 2026-05-25 reproduje un smoke en Railway: los tres runtimes desplegaron contra un PostgreSQL disposable, pasaron /ready, tracking read y un k6 mínimo (1 VU / 10s) sin check failures. Eso me alcanza para decir “esto se mueve fuera de mi máquina” y me cuadra con cómo vengo operando juanchi.dev en Railway. No lo uso para inferir performance de producción.



Tabla Phase 2 vs Phase 4 (qué cambió cuando el benchmark fue justo)


























Fase Lectura rápida Qué faltaba o qué se agregó Quién quedó mejor posicionado
Phase 2 GlassFish parecía liderar en p95/throughput Sin pg_stat_statements, sin warmup separado, muestras cortas, JDK no uniformado, pools no explícitos GlassFish (aparente), pero con método incompleto
Phase 4 JDK soportado, heap fijo, warmup, 180s de ventana, pools explícitos, DB attribution Sí a todo lo que faltaba Spring Boot en latencia/throughput locales; Payara Micro sin check failures; GlassFish viable


Decision tree (lo que me llevo a la práctica)




  • Greenfield con equipo que ya conoce Spring: Spring Boot. Razones: menor fricción de adopción, ecosistema, observabilidad, hiring y en este lab mejor perfil local Phase 4.

  • Organización con Payara/Jakarta/WAR ya instalada: probar Payara Micro antes de proponer migración. En el lab fue el Jakarta EE más limpio bajo presión (check failures 0) y competitivo en throughput.

  • Código Jakarta que busca ejecutable más liviano y no necesita app server completo: evaluar Embedded GlassFish. Es más viable de lo que muchos piensan y puede ser el puente sin reescritura total.

  • Discusión de migración por performance: correr un benchmark propio con el workload real de ese sistema. No alcanza con un post (ni con este).

  • Si la decisión está dominada por operabilidad, integraciones y contratación: Spring Boot suele reducir riesgo para equipos como el mío.



Límites honestos (para no vender humo)




  • Una sola workstation para Phase 4.

  • Workload DB-heavy; no aísla runtime puro.

  • Sin Kafka, PostGIS, native image, Kubernetes ni autoscaling.

  • Sin soak test largo.

  • Phase 5 es smoke externo, no matriz de performance.

  • La experiencia de desarrollo está sesgada por familiaridad previa con Spring Boot.

  • Logs de los runtimes Jakarta requieren interpretación y hay que contarlo, no esconderlo.

  • Los check failures de Spring Boot en Phase 4 están preservados y mencionados; el root cause exacto no quedó completamente probado en esa sesión.



Lo que cambiaría si repito este lab mañana




  • Corridas más largas todavía en presión (y un soak de varias horas) para capturar variación lenta.

  • Replicación en otra máquina o en un runner CI para eliminar ruido local.

  • Captura completa de consola k6 y stderr/stdout ya automatizada en el harness.

  • Un pasito más en sintonía de pools iguales (Hikari en todos con mismas políticas finas) y límites de conexión en PostgreSQL para ver si la cola se mueve.

  • Una versión con workload más CPU-bound (menos agregaciones pesadas) para aislar runtime/serializer.



Cómo encaja esto con mi trabajo actual



En mi día a día construyo backends Java/Spring Boot en un equipo chiquito que resuelve identidad digital, biometría, firma y storage. Hay mucha presión por entregar y por operar con confianza. Por eso, aunque Jakarta EE moderno me parezca viable (y después de este lab me lo parece más), en greenfield elijo Spring Boot. El costo marginal de ponerse en modo productivo y la claridad operativa siguen pesando. Al mismo tiempo, si llego a un cliente con Payara en producción y WARs estables, hoy tengo evidencia para decir “probemos Payara Micro y/o Embedded GlassFish antes de planear una reescritura entera”.



Qué me sorprendió en serio (el momento eureka)



El eureka fue cuando vi que, con Temurin 21 para todos, heap fijo y warmup serio, el ranking cambió. No fue que Spring “se volvió más rápido por arte de magia”; fue que la comparación se ordenó. Y que el factor dominante del p99 bajo presión estaba en la base, no en un if del framework. A partir de ahí el debate deja de ser religioso y se vuelve arquitectónico: ¿qué estoy midiendo de verdad?, ¿qué quiero optimizar?, ¿qué trade-off me conviene para este equipo?



Qué cambiaron los briefs en este post



Este post no salió de una sola generación ni de una tabla linda. Lo traté como un paquete editorial: primero armé el experimento, después escribí briefs para separar evidencia, claims permitidos, claims prohibidos y límites. Eso cambió bastante el texto final.



Los briefs me obligaron a frenar tres veces:




  • No publicar Phase 2 como si fuera la verdad, aunque tenía más punch, porque todavía faltaban controles de fairness.

  • No esconder los check failures de Spring Boot en Phase 4: si están en la evidencia, tienen que estar en el post.

  • No vender Railway como benchmark de producción: Phase 5 fue smoke externo y portabilidad, no podio de performance.



La trazabilidad quedó pública en el repo: . También dejé el y la nota de , con tag canónico

Vollständiger Original-Artikel
Den kompletten Beitrag mit allen Details direkt auf dev.to lesen.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Juicebox vs Noon: How much of sourcing should AI own?
1 Quelle
Two Cloudflare Pages behaviours I had to measure to believe
1 Quelle
I Built a Fun Name-Based Love Calculator — Here's How It Works
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten El benchmark que me hizo cambiar de opinión sobre Jakarta EE en 2026

Thematisch verwandte Begriffe: benchmark, hizo, cambiar, opinión · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...