Inicio / Artículos / Express frente a Fastify en 2026: Una comparación práctica de frameworks para Node.js

Express frente a Fastify en 2026: Una comparación práctica de frameworks para Node.js

Esta guía compara a Express y Fastify en términos de rendimiento, validación, ecosistema y manejo de errores, además aborda los principales cambios que rompen la compatibilidad en Express 5.

2543 palabras

Imagínese un equipo que da inicio a un nuevo backend en Node.js.

Comienzan a investigar frameworks, y casi de inmediato dos nombres dominan la conversación:

Express.js y Fastify.

Luego aparecen los gráficos de pruebas de rendimiento.

En numerosas pruebas sintéticas, Fastify muestra cifras de rendimiento notablemente más altas.

La reacción natural es:

"Si Fastify gana en velocidad, ¿por qué alguien seguiría usando Express?"

A primera vista es una pregunta legítima.

Pero elegir un framework para backend rara vez se reduce a una sola métrica de ese tipo.

Las solicitudes brutas por segundo son solo una parte del rompecabezas. También es necesario considerar el ecosistema circundante, cómo funciona el middleware, la validación integrada, el soporte para TypeScript, cuán costosa sería una migración, la experiencia diaria del desarrollador, cualquier base de código existente que esté manteniendo y qué exige realmente su aplicación específica.

También hay una segunda capa en esta comparación que merece atención.

Express 5 ya está oficialmente disponible.

Tras un largo uso de Express 4, esta nueva versión principal introduce algunos cambios de los que debe estar al tanto todo aquel que mantenga una base de código antigua de Express.

Con ese contexto establecido, analicemos qué es lo que realmente diferencia a Express de Fastify, y, más útilmente aún, las situaciones en las que cada uno resulta adecuado.

Primero: ¿Qué son exactamente Express y Fastify?

Ambos frameworks existen para ayudarte a crear servidores web sobre Node.js.

En esencia, te evitan tener que escribir directamente con el módulo HTTP de nivel inferior de Node, al ofrecerte una API más limpia para definir rutas y manejar solicitudes.

Así es como se ve un servidor Express mínimo:

const express = require("express");

const app = express();
app.get("/users", (req, res) => {
  res.json([
    { id: 1, name: "Neha" },
    { id: 2, name: "Rahul" }
  ]);
});
app.listen(3000);

El punto de partida de Fastify es bastante similar:

const fastify = require("fastify")({
  logger: true
});

fastify.get("/users", async (request, reply) => {
  return [
    { id: 1, name: "Neha" },
    { id: 2, name: "Rahul" }
  ];
});
fastify.listen({ port: 3000 });

¿Notas algo?

Ninguno de los ejemplos resulta especialmente intimidante.

La verdadera diferencia entre ambos solo se vuelve evidente una vez que tu aplicación supera esta etapa de ejemplo sencillo.

Express vs Fastify: La visión general

Veamos por qué las diferencias entre estos dos frameworks son realmente importantes en la práctica.

1. Rendimiento: Fastify tiene la ventaja

Probablemente esta sea la razón principal por la que Fastify aparece constantemente en estas conversaciones.

El rendimiento y la mínima carga adicional fueron objetivos fundamentales en el diseño de Fastify desde un principio.

Sus componentes internos dependen en gran medida de esquemas tanto para validar los datos entrantes como para serializar las respuestas salientes, lo que puede mejorar significativamente el rendimiento en cargas de trabajo intensivas en API. La propia documentación de Fastify recomienda utilizar JSON Schema específicamente para la validación de rutas y la serialización de respuestas.

No obstante, existe una advertencia importante aquí.

No se debe basar únicamente en un único resultado de pruebas para llegar a la conclusión de que:

Fastify implica automáticamente una aplicación 3 veces más rápida.

La mayoría de las pruebas de rendimiento de los frameworks miden la carga adicional del propio framework, en condiciones estrictamente controladas.

Los propios mantenedores de Fastify reconocen que su prueba de rendimiento publicada es una prueba sintética al estilo “hello world”, y sugieren explícitamente realizar pruebas de rendimiento con su propia aplicación real si el rendimiento es una prioridad para usted.

Considere un flujo de solicitudes que se ve así:

Request
   ↓
Authentication
   ↓
Database query
   ↓
Redis
   ↓
External API
   ↓
Business logic
   ↓
Response

Si solo la llamada a la base de datos tarda 80 milisegundos, reducir ligeramente la carga adicional del framework no va a cambiar significativamente la velocidad de ese endpoint.

Por lo tanto, la verdadera pregunta que debe hacerse es:

¿Está mi aplicación realmente limitada por la CPU o por la carga adicional del framework?

En otras palabras: ¿es el propio framework lo que ralentiza las solicitudes? Si la respuesta es sí, cambiar a Fastify tiene una justificación mucho más sólida.

Si la respuesta es no, entonces las pruebas de rendimiento genéricas del framework probablemente no deberían ser el factor decisivo.

2. Validación: Aquí es donde Fastify se vuelve interesante

Imagínese que su API está diseñada para aceptar una carga de trabajo con esta estructura:

{
  "name": "Neha",
  "age": 25
}

Naturalmente, querrá rechazar una versión mal formada de esa misma carga de trabajo, algo como:

{
  "name": 123,
  "age": "hello"
}

En el mundo de Express, los equipos suelen recurrir a una biblioteca adicional para manejar este tipo de validación de solicitudes. Fastify adopta un enfoque diferente: la validación basada en esquemas está integrada directamente en el propio framework.

Así es como se ve en la práctica:

const schema = {
  body: {
    type: "object",
    required: ["name", "age"],
    properties: {
      name: { type: "string" },
      age: { type: "integer" }
    }
  }
};

fastify.post("/users", { schema }, async (request, reply) => {
  return { message: "User created" };
});

Fastify le permite definir definiciones de JSON Schema para varias partes del ciclo de solicitud y respuesta, incluyendo:

  • el cuerpo de la solicitud
  • parámetros de consulta
  • parámetros de ruta
  • encabezados
  • serialización de la respuesta

En el fondo, Fastify depende de Ajv para gestionar esta capa de validación, y las mismas definiciones de esquema también pueden utilizarse para acelerar la serialización de las respuestas.

Ajv, abreviatura de “Another JSON Schema Validator”, es una biblioteca rápida y compatible con estándares para validar objetos de datos en JavaScript según las definiciones de JSON Schema, y funciona tanto en Node.js como en el navegador.

Este enfoque basado en los esquemas se vuelve especialmente valioso cuando la superficie de tu API crece y incluye una gran cantidad de datos estructurados de entrada y salida.

3. Express tiene algo que Fastify no puede reemplazar fácilmente: su ecosistema

Express existe desde 2010, lo que significa que existe una enorme cantidad de conocimiento acumulado, herramientas y experiencia comunitaria desarrollada en torno a él.

  • Necesitas autenticación? Existe un paquete para ello.
  • Necesitas registro de actividades? También existe un paquete para eso.
  • ¿Necesita manejo de CORS? Existe un paquete para ello.
  • ¿Necesita validación? También hay un paquete para eso.
  • ¿Está atascado con algún bug poco común? Es probable que otra persona ya lo haya encontrado y documentado una solución.
  • Esa profundidad en el ecosistema es más importante de lo que parece a primera vista.

    Imagínese unirse a una empresa cuyo backend lleva seis años en producción. No puede elegir el framework desde cero, debe utilizar lo que ya existe, que podría verse algo así:

    Express
     ├── 200+ routes
     ├── authentication middleware
     ├── custom middleware
     ├── logging
     ├── validation
     ├── monitoring
     └── lots of business logic
    

    ¿Tendría sentido reescribir todo eso solo porque Fastify es más rápido según las pruebas? Probablemente no.

    Migrar una base de código existente siempre conlleva costos, y cualquier decisión de ingeniería real debe sopesar esos costos frente al beneficio esperado.

    4. Middleware vs Plugins

    También existe una distinción arquitectónica más profunda entre los dos frameworks.

    Express se basa en el concepto de middleware. Una configuración típica podría verse así:

    app.use(authMiddleware);
    app.use(loggingMiddleware);
    app.use(express.json());
    

    Cada solicitud entrante pasa entonces secuencialmente por estas funciones de middleware.

    Fastify, en contraste, utiliza una arquitectura basada en plugins, construida a partir de ganchos y encapsulamiento. Conceptualmente, el flujo se parece más a esto:

    Request
       ↓
    Fastify
       ↓
    Hooks
       ↓
    Plugins
       ↓
    Route
       ↓
    Response
    

    Para aplicaciones diseñadas desde el principio según el modelo de Fastify, esta estructura puede hacer que los conjuntos de código más grandes sean más fáciles de organizar y comprender.

    No obstante, existe un trade-off. Si has pasado años desarrollando modelos mentales basados en el middleware al estilo de Express, adaptarse al sistema de plugins y ganchos de Fastify puede resultar algo extraño al principio.

    5. Manejo de errores

    En Express 4, manejar errores provenientes de los controladores de rutas asíncronos solía requerir redirigirlos manualmente. Un patrón típico era el siguiente:

    app.get("/user/:id", async (req, res, next) => {
      try {
        const user = await getUserById(req.params.id);
        res.json(user);
      } catch (error) {
        next(error);
      }
    });
    

    Express 5 simplifica esto considerablemente. Ahora, las rechazos de promesas generados por los controladores de rutas o el middleware se transmiten automáticamente al middleware de manejo de errores, lo que permite escribir código mucho más compacto:

    app.get("/user/:id", async (req, res) => {
      const user = await getUserById(req.params.id);
      res.json(user);
    });
    

    Si getUserById() lanza un error o lo rechaza, Express 5 lo captura automáticamente y lo dirige al manejador de errores, sin necesidad de usar explícitamente try/catch ni llamar a next(err).

    A primera vista, esto parece una pequeña conveniencia sintáctica. Pero en un código con cientos de rutas, este tipo de mejoras menores contribuyen a un código notablemente más ordenado y menos propenso a errores.

    Express 5: ¿Qué cambió realmente?

    Express 5 llegó en octubre de 2024, por lo que al entrar en 2026 ya no se trata de una versión reciente. Aun así, un gran número de aplicaciones en producción funcionan con Express 4, lo que significa que comprender qué cambió entre las versiones es de suma importancia para quienes planean una actualización.

    Sí, existen cambios que pueden causar problemas y de los cuales debe estar al tanto.

    1. Se han modificado los parámetros de ruta opcionales

    En Express 4 es posible que haya escrito una ruta de esta manera:

    app.get("/:file.:ext?", handler);
    

    Express 5 reemplaza ese patrón por:

    app.get("/:file{.:ext}", handler);
    

    La antigua notación ? para indicar que un parámetro es opcional ya no funciona.

    ¿Por qué este cambio?

    La nueva sintaxis permite ver de inmediato qué parte de la ruta es opcional.

    A simple vista parece un cambio sutil, pero puede afectar silenciosamente a decenas de rutas en una aplicación grande y establecida.

    2. Se han modificado las rutas con comodines

    Anteriormente, una ruta genérica podría verse así:

    app.get("/*", handler);
    

    Express 5 exige que los comodines tengan un nombre:

    app.get("/*splat", handler);
    

    Si necesita que ese comodín también coincida con la ruta raíz /, envuélvalo de esta manera:

    app.get("/{*splat}", handler);
    

    Este es otro pequeño cambio en la sintaxis que puede romper silenciosamente la lógica de enrutamiento existente durante una actualización.

    3. Se han modificado los patrones de ruta con expresiones regulares

    Express 5 deja de soportar varios de los antiguos patrones basados en cadenas que utilizaban caracteres al estilo regex.

    Por ejemplo, en lugar de incrustar segmentos alternativos directamente en una única cadena de ruta, ahora normalmente se pasa un array de rutas:

    app.get(
      ["/discussion/:slug", "/page/:slug"],
      handler
    );
    

    La intención detrás de este cambio es mantener la coincidencia de rutas explícita y predecible, en lugar de depender de atajos similares a regex.

    4. req.body ahora puede ser undefined

    Este es un detalle sutil que es fácil pasar por alto.

    En Express 4, era común asumir que:

    req.body
    

    se usaría por defecto un objeto vacío incluso antes de que ocurriera cualquier procesamiento.

    Bajo Express 5, si nada procesa el cuerpo de la solicitud, req.body puede ser simplemente undefined.

    Eso significa que una verificación defensiva como esta se vuelve relevante según la ruta:

    if (!req.body) {
      return res.status(400).send("Request body required");
    }
    

    Es un pequeño cambio en el comportamiento, pero exactamente ese tipo de detalle que puede introducir errores difíciles de rastrear después de una actualización.

    5. express.urlencoded() ha cambiado

    El valor por defecto de la opción extended ahora es false.

    Así que, en lugar de depender del valor por defecto implícito:

    app.use(express.urlencoded());
    

    será mejor establecerlo explícitamente si su aplicación depende del comportamiento anterior:

    app.use(
      express.urlencoded({
        extended: true
      })
    );
    

    Otro detalle que merece una auditoría cuidadosa al migrar una base de código existente.

    6. Cambios en el analizador del cuerpo

    Express 5 también mejoró la forma en que se procesa internamente el cuerpo de las solicitudes.

    Ahora puede escribirse:

    app.use(express.json());
    app.use(
      express.urlencoded({
        extended: false
      })
    );
    

    en lugar de combinar paquetes separados de middleware body-parser como antes.

    Además, Express 5 añade soporte para cuerpos de solicitud comprimidos con Brotli y permite configurar la profundidad máxima permitida para los datos codificados en URL.

    7. Se eliminaron algunas APIs antiguas de respuesta

    Imagínese una aplicación Express más antigua que contuviera algo como:

    res.send({
      message: "Success"
    }, 200);
    

    Bajo Express 5, el formato esperado es:

    res
      .status(200)
      .send({
        message: "Success"
      });
    

    De manera similar, el atajo antiguo:

    res.redirect("back");
    

    ha sido eliminado por completo.

    La guía oficial de migración sugiere leer manualmente el encabezado referrer y recurrir a una ruta predeterminada cuando está ausente.

    Ninguno de estos cambios individuales es particularmente difícil de solucionar.

    Pero imagina una base de código heredada con miles de llamadas escritas a la antigua usanza.

    A esa escala, la actualización deja de ser un simple ajuste en las dependencias y se convierte en un verdadero esfuerzo de ingeniería por sí mismo.

    Entonces, Express o Fastify: ¿cuál gana?

    A estas alturas ya tienes suficiente contexto como para tomar una decisión real.

    No lo basaría únicamente en:

    "¿Cuál tiene mejores resultados en pruebas de rendimiento?"

    En lugar de eso, comienza analizando la aplicación en sí.

    Razones para seguir usando Express:

    • Apenas estás comenzando con el desarrollo backend en Node.js.
    • Tu equipo ya está familiarizado con Express.
  • Estás manteniendo o ampliando una base de código Express existente.
  • Tu proyecto depende en gran medida de middleware al estilo Express.
  • Deseas tener acceso al ecosistema más amplio posible de paquetes.
  • El rendimiento bruto no es la principal limitación a la que te enfrentas.
  • Preferirías algo simple y flexible en lugar de algo rígido con reglas estrictas.
  • Razones para considerar Fastify:

    • Estás creando desde cero un servicio nuevo centrado en APIs.
    • El rendimiento y la minimización de la carga del framework sí son importantes.
    • Deseas que la validación se realice directamente mediante esquemas.
    • También deseas que la serialización se gestione a través de esquemas.
    • Estás desarrollando microservicios.
    • Te gusta trabajar con una arquitectura basada en plugins.
    • No te importa adoptar un ecosistema algo más reciente.

    No hay nada intrínsecamente incorrecto en elegir Express incluso para un sistema a gran escala.

    El hecho de tratarse de una “aplicación grande” no significa automáticamente que Fastify sea la mejor opción.

    Lo que rodea al framework —su arquitectura general— suele ser mucho más importante que la elección del propio framework.

    Una forma básica de analizarlo

    Aquí hay un flujo mental aproximado para tomar la decisión:

    Start
                       │
                       ▼
              Is this an existing app?
                  /           \
                Yes            No
                 │              │
                 ▼              ▼
           Already using     Need very high
            Express?         throughput?
             /    \           /       \
           Yes     No       Yes        No
            │       │        │          │
            ▼       ▼        ▼          ▼
         Keep    Evaluate  Fastify    Evaluate
        Express  migration           both
    

    Antes de decidir definitivamente, hay una pregunta más que vale la pena hacer:

    ¿Qué problema estoy tratando de resolver realmente?

    Si tu aplicación Express actual parece lenta, resiste la tentación de culpar al framework de inmediato.

    Primero haz un análisis de rendimiento.

    El verdadero culpable podría ser:

    Slow API
       ↓
    Database query
       ↓
    Missing index
    

    o:

    Slow API
       ↓
    External API
       ↓
    3-second response time
    

    o:

    Slow API
       ↓
    Expensive business logic
       ↓
    CPU bottleneck
    

    Cambiar de framework por sí solo no resolverá ninguno de estos problemas subyacentes.

    Mi opinión al respecto

    Si hoy comenzaras un nuevo proyecto pequeño en Node.js, descartar Express solo porque Fastify muestra mejores resultados en pruebas de rendimiento no tendría mucho sentido. Express cuenta con un ecosistema enorme, un modelo conceptual sencillo y años de conocimiento acumulado en torno a él.

    Dicho esto, tampoco se debe pasar por alto a Fastify. Para un servicio nuevo donde el rendimiento, la validación de esquemas, la serialización y una carga mínima del framework son realmente importantes, Fastify merece ser considerado seriamente.

    Y si heredaste una aplicación existente de Express 4, reescribirla únicamente porque Fastify es más rápido sería un error.

    El enfoque más adecuado es comprender primero la aplicación, medir dónde se encuentran los cuellos de botella reales, verificar la compatibilidad con Express 5, realizar las pruebas de migración y solo entonces decidir si cambiar de framework aporta un valor real suficiente como para justificar el esfuerzo.

    Esa es probablemente la conclusión principal aquí.

    El framework con las mejores pruebas de rendimiento no es automáticamente el más adecuado para tu situación.

    El framework correcto es aquel que resuelve tu problema real al tiempo que añade la menor cantidad posible de complejidad innecesaria.

    Lecturas relacionadas