|

Bun en Lambda: 3x más rápido, pero ¿listo para producción?

Corrimos Bun en producción en AWS Lambda durante 60 días y los números son reales: 823ms contra 2456ms para tareas CPU-intensivas. Eso es casi 3x más rápido que Node.js 22. El problema es lo que descubrimos en el camino.

En 30 segundos

  • Bun completó una tarea CPU-intensiva en 823ms vs 2456ms de Node.js 22 en Lambda, según pruebas de 60 días en producción real
  • El runtime personalizado de Bun agrega 3-5MB al paquete de deployment, lo que impacta el cold start
  • Módulos con código nativo (bcrypt, sharp, node-canvas) no funcionan en Bun, lo cual rompe muchos proyectos existentes
  • El cliente S3 nativo de Bun genera errores de firma distintos a los del SDK de AWS, lo que puede enmascarar fallas en producción
  • Para funciones IO-heavy (el 95% de los casos reales), la ventaja de velocidad se reduce considerablemente

Llama 3 es un modelo de lenguaje grande desarrollado por Meta, disponible en versiones de 8 mil millones y 70 mil millones de parámetros, diseñado para procesamiento del lenguaje natural, generación de texto y asistencia en tareas de codificación. Fue lanzado en 2024 como evolución de Llama 2.

Bun es un runtime de JavaScript construido sobre JavaScriptCore (el motor de Safari) en lugar de V8, escrito mayormente en Zig, que promete inicialización más rápida y menor consumo de memoria que Node.js en entornos serverless como AWS Lambda.

Bun vs Node.js 22: Los números reales del benchmark

Los benchmarks sintéticos de Bun son llamativos. En pruebas HTTP puras, algunos miden hasta 4x de diferencia. Pero en Bun en Lambda producción, con código real y base de datos de por medio, la historia cambia.

Según el reporte de 60 días, el test que usaron fue una Lambda con una tarea CPU-intensiva corriendo sobre el paquete @aws-sdk/client-lambda. Resultado: Node.js 22 tardó 2456ms, Bun 823ms. Eso es una diferencia de ~66%.

Eso sí: ese benchmark mide carga de CPU pura. Ponele que tu función hace consultas a DynamoDB o procesa un JSON de 200KB y devuelve una respuesta. En ese escenario, la diferencia baja a un rango de 3-10% según mediciones independientes en Lambda. No es nada despreciable, pero tampoco es el “3x” que aparece en el titular.

EscenarioNode.js 22BunDiferencia
CPU-intensiva (benchmark)2456ms823ms~3x
HTTP sintéticoBaseBase~4x (labs)
IO-heavy (DB + red)BaseBase~3-10%
Cold startMás rápido+500ms extraBun pierde
bun en lambda producción diagrama explicativo

¿Por qué Bun es tan rápido en Lambda?

Dos razones concretas: el motor y el lenguaje de implementación.

JavaScriptCore, el motor de WebKit que usa Bun, tiene un pipeline de compilación JIT diferente a V8. Para ciertas cargas de trabajo (especialmente las computacionalmente intensivas), arranca más rápido y consume menos memoria en las primeras iteraciones. Además, Bun está escrito en Zig, un lenguaje de sistemas sin garbage collector en runtime, lo que reduce el overhead de administración de memoria.

En el contexto de Lambda, esto importa porque cada invocación fría arranca desde cero. Un runtime que inicializa su heap más rápido y ejecuta el bootstrap en menos tiempo tiene ventaja directa en el primer request. Esto se conecta con lo que analizamos en elegir la herramienta de CI/CD correcta.

El tema es que “más rápido en startup” y “más rápido en ejecución” no son lo mismo. Y acá viene el matiz que los benchmarks no siempre muestran.

Los gotchas reales: Qué se rompió en 60 días

El reporte de producción es honesto con esto, y vale citarlo directo.

El primer problema grave fue con el cliente S3 nativo de Bun. Cuando usás el SDK de AWS estándar (@aws-sdk/client-s3) compilado para correr sobre Bun, los tipos de error que lanza el cliente S3 propio de Bun son distintos. El error concreto que reportaron: “The request signature we calculated does not match the signature you provided. Check your key and signing method.” El mismo código, las mismas credenciales, pero Bun firma las requests de manera diferente (o el cliente las interpreta diferente). ¿Alguien lo verificó de forma independiente con la versión estable actual? Todavía hay reportes abiertos sobre esto.

El segundo gotcha es el tamaño del deployment package. El runtime personalizado de Bun para Lambda agrega entre 3 y 5MB al ZIP final. En funciones pequeñas esto puede significar pasar de 2MB a 7MB, lo que impacta el cold start real (Lambda demora más en descomprimir y cargar el paquete).

Compatibilidad: Módulos nativos que no funcionan

Bun pasa aproximadamente el 90% de la suite de tests de Node.js. Ese 10% restante duele cuando te cae encima en producción.

Los módulos que usan addons nativos en C++ directamente no funcionan. La lista incluye bcrypt (autenticación de passwords), sharp (procesamiento de imágenes), node-canvas (generación de imágenes en servidor) y cualquier otro módulo que compile código nativo en la instalación. Si tu función usa alguno de estos, no podés migrar sin encontrar alternativas. Relacionado: expandir a mercados internacionales.

Hay un caso real documentado con Payload CMS: el framework rompió porque tiene dependencias que asumen una implementación específica de Node.js a nivel de módulos internos. No es un caso extremo, es un CMS mainstream. Tomalo como señal de cuántas dependencias “normales” pueden tener supuestos que Bun no cumple.

Cold start vs hot start: El lado B de la velocidad

Acá está el dato que más cambia el análisis.

La inicialización de Bun en Lambda agrega más de 500ms al cold start. Node.js 22 arranca más rápido en la primera invocación. Eso importa especialmente en funciones que se invocan esporádicamente (un webhook, un job puntual, una API que no tiene tráfico constante), porque en esos casos casi siempre estás en cold start.

Una vez que la función está “caliente”, Bun gana. Pero si tu patrón de uso genera cold starts frecuentes (porque las invocaciones están muy separadas en el tiempo o porque usás Provisioned Concurrency con poco presupuesto), la ventaja de Bun en ejecución se come por el cold start más lento.

La mayoría de las funciones Lambda reales son IO-heavy: esperan una query a RDS, llaman a una API externa, procesan un evento de SQS. En esos casos, el tiempo que el proceso espera bloqueado en I/O es el mismo sin importar si el runtime es Bun o Node. La diferencia de velocidad queda enterrada en el tiempo de espera.

Estrategia de migración: De Node.js a Bun paso a paso

Si decidís probarlo, el proceso tiene pasos concretos que no podés saltear:

  • Auditá las dependencias npm: corré bun install en el proyecto y fijate qué paquetes tienen postinstall scripts que compilan código nativo. Si hay alguno, buscá alternativa o descartá la migración.
  • Ejecutá tu test suite completo con Bun: bun test es compatible con Jest en la mayoría de los casos. Si tus tests pasan, tenés una base de confianza. Si fallan, ya sabés dónde están los problemas antes de tocar producción.
  • Deploy en staging primero: obvio, pero en serio, no lo saltees. El runtime personalizado de Bun para Lambda se configura con una layer custom o un bootstrap script. Probalo con tráfico real de staging antes de cualquier cutover.
  • Validá el manejo de errores del AWS SDK: revisá específicamente todas las llamadas a S3 y cualquier servicio que use signing. Los tipos de error son distintos y si tenés catch genéricos que no discriminan el tipo de error, podés enmascarar fallas sin darte cuenta.
  • Medí cold starts en producción: no asumas que el benchmark de CPU aplica a tu caso. Habilitá X-Ray o usá CloudWatch Insights para ver la distribución real de duración, separando init time de execution time.

¿Debería migrar? Matriz de decisión por caso de uso

No hay respuesta universal. Hay contextos donde tiene sentido y contextos donde es ruido. Lo explicamos a fondo en evitar pruebas inestables en CI.

Caso de uso¿Migrar a Bun?Motivo
Procesamiento CPU intensivo (imágenes, criptografía JS pura, parsing)Sí, vale la pena probarAcá está la ganancia real de 2-3x
Funciones serverless con pocas dependencias nativasSí, con auditoría previaRiesgo bajo si el stack es simple
APIs IO-heavy (DB, external APIs, queues)Probablemente noLa ganancia real es de 3-10%, no justifica el riesgo
Proyectos con bcrypt, sharp, node-canvasNo por ahoraEsos módulos no funcionan en Bun
Equipos sin tiempo de auditar dependencias y monitorearNoEl costo operativo supera el beneficio
Funciones con cold starts frecuentesNoBun agrega >500ms al cold start

Para proyectos que necesiten hosting del resultado final en la web, la infraestructura de donweb.com puede complementar el backend serverless con frontend estático o servicios adicionales.

Qué está confirmado y qué no

  • Confirmado: Bun ejecuta tareas CPU-intensivas ~3x más rápido que Node.js 22 en Lambda (823ms vs 2456ms en benchmark propio)
  • Confirmado: El runtime agrega 3-5MB al deployment package
  • Confirmado: Los módulos con código nativo en C++ no funcionan (bcrypt, sharp, node-canvas)
  • Confirmado: El cold start de Bun es más lento que Node.js 22 (>500ms adicionales)
  • No confirmado de forma independiente: Si los problemas de firma con S3 están resueltos en las últimas versiones del runtime custom de Bun para Lambda
  • No confirmado: Qué porcentaje exacto de mejora se obtiene en funciones IO-heavy con tráfico real de producción (los datos disponibles son de CPU-bound tasks)

Errores comunes al evaluar Bun en Lambda

Extrapolar el benchmark de CPU a todas las funciones. El 3x aplica a tareas computacionalmente intensivas. Si tu función pasa el 80% del tiempo esperando una query a Postgres, ese 3x se convierte en ruido estadístico. Medí tu caso específico antes de decidir.

Ignorar el cold start en el análisis de performance. La mayoría de los comparativos muestran “tiempo de ejecución” sin separar el init time. En funciones que no tienen tráfico constante, Bun puede ser más lento en el total del request que Node.js 22, porque el cold start más largo cancela la ventaja de ejecución.

Asumir que “pasa el 90% de tests de Node.js” significa que tu proyecto funciona. El 10% que falla puede incluir exactamente el módulo que tu proyecto usa más. Corré tu suite de tests completa en Bun antes de sacar conclusiones. No confíes en el promedio general.

Preguntas Frecuentes

¿Es Bun realmente más rápido que Node.js 22 en Lambda?

Depende del tipo de tarea. Para procesamiento CPU-intensivo, sí: los benchmarks muestran 823ms en Bun contra 2456ms en Node.js 22 en la misma función. Para funciones IO-heavy (la mayoría de los usos reales), la diferencia cae a un rango de 3-10%. El cold start de Bun además agrega más de 500ms, lo que puede cancelar la ventaja si las invocaciones son esporádicas.

¿Puedo usar Bun en producción en AWS Lambda hoy?

Podés, pero con condiciones. Si tu proyecto no tiene dependencias con código nativo en C++ y tu equipo puede auditar y monitorear la migración, es viable. Si usás módulos como bcrypt, sharp o node-canvas, no podés migrar sin reemplazarlos primero. Para la mayoría de proyectos con stacks complejos, el riesgo operativo supera el beneficio de velocidad en 2026. En evaluar estrategias multi-cloud profundizamos sobre esto.

¿Qué módulos de Node.js no funcionan en Bun?

Cualquier módulo que use addons nativos en C++ falla en Bun. Los casos más comunes son bcrypt (hashing de passwords), sharp (procesamiento de imágenes), node-canvas (renderizado en servidor) y algunos drivers de bases de datos con bindings nativos. Bun pasa aproximadamente el 90% de la suite de compatibilidad de Node.js, pero ese 10% puede ser crítico para tu proyecto.

¿Vale la pena migrar de Node.js a Bun en Lambda?

Para funciones CPU-intensivas con pocas dependencias externas y tráfico constante (lo que minimiza el impacto del cold start más lento), sí tiene sentido evaluarlo. Para el resto, el costo operativo de la migración (auditoría de dependencias, validación de errores del AWS SDK, monitoreo adicional) probablemente no justifique una ganancia de performance de 3-10% en el tiempo total del request.

¿Qué pasa con el AWS SDK y los errores de firma en Bun?

El cliente S3 nativo de Bun genera errores de firma diferentes al SDK estándar de AWS. En producción esto se manifestó como: “The request signature we calculated does not match the signature you provided.” El problema es que si tenés catch handlers genéricos, podés estar enmascarando estos errores sin saberlo. Validá explícitamente el comportamiento de todas las llamadas al AWS SDK, especialmente S3 y cualquier servicio que use request signing.

Conclusión

Bun en Lambda producción es real, funciona, y para ciertos casos de uso específicos tiene una ventaja de performance que ningún tuning de Node.js va a replicar. El 3x en tareas CPU-intensivas no es marketing, es un benchmark de 60 días con código real.

El problema es que la mayoría de las funciones Lambda no son CPU-intensivas. Son IO-heavy, tienen dependencias acumuladas de años, y los equipos que las mantienen no siempre tienen el ancho de banda para auditar dependencias, reemplazar módulos nativos y validar el comportamiento del AWS SDK en un runtime alternativo.

Si tu función hace número-cruning, parsing pesado o criptografía en JS puro, probá Bun en staging ahora. Si tu función espera bases de datos y llama APIs externas, el esfuerzo de migración probablemente no valga el 5% de mejora que vas a ver en producción real. Medí antes de decidir.

Fuentes

Te puede interesar...