Fastify para JavaScript (Node.js): guía completa con ejemplos
1. ¿Qué es y para qué sirve?
Fastify es un framework web de alto rendimiento para Node.js, inspirado en Hapi y Express, pero centrado en la velocidad y el bajo consumo de memoria. Fue creado en 2016 por desarrolladores del equipo NearForm y desde entonces se ha convertido en una de las soluciones más rápidas para crear APIs REST, microservicios y aplicaciones web en JavaScript/TypeScript.
La principal razón para usar Fastify es su rendimiento. Según pruebas, puede procesar entre un 30 y un 40% más de solicitudes por segundo en comparación con Express, consumiendo los mismos recursos. Esto se logra gracias a su arquitectura asíncrona basada en Node.js streams, el análisis eficiente de JSON (mediante fast-json-stringify) y un enrutador optimizado basado en Radix Tree (árbol de prefijos comprimido).
Además de la velocidad, Fastify ofrece validación de esquemas integrada mediante JSON Schema, almacenamiento en caché automático de respuestas, soporte nativo para TypeScript, un sistema de plugins extensible y una documentación excelente. Esto lo convierte en la opción ideal para proyectos en producción donde la estabilidad y el rendimiento predecible bajo carga son fundamentales.
2. Instalación
Fastify se instala a través de npm (Node Package Manager). Asegúrate de tener instalado Node.js versión 18 o superior (se recomienda la versión LTS).
# Instalación básica
npm install fastify
# Para TypeScript (adicional)
npm install -D @types/node typescript
# Para trabajar con cookies, sesiones, etc.
npm install @fastify/cookie @fastify/session
Si usas yarn o pnpm:
yarn add fastify
# o
pnpm add fastify
3. Inicio rápido — ejemplo mínimo funcional
Crea un archivo server.js y ejecútalo con node server.js.
// server.js
const fastify = require('fastify')({
logger: true // Activamos el registrador integrado (pino)
});
// Definimos la ruta GET /
fastify.get('/', async (request, reply) => {
return { hello: 'world' };
});
// Iniciamos el servidor
const start = async () => {
try {
await fastify.listen({ port: 3000 });
console.log('Servidor iniciado en http://localhost:3000');
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();
Después de iniciarlo, abre el navegador o ejecuta curl http://localhost:3000. Recibirás la respuesta JSON {"hello":"world"}.
4. Métodos/funciones/clases principales
4.1. fastify.get(path, options, handler)
Firma: fastify.get(path: string, opts?: RouteShorthandOptions, handler: RequestHandler)
Qué hace: Registra un manejador para solicitudes HTTP GET en la ruta especificada.
fastify.get('/user/:id', async (request, reply) => {
const { id } = request.params;
return { userId: id, name: 'Juan Pérez' };
});
4.2. fastify.post(path, options, handler)
Firma: fastify.post(path: string, opts?: RouteShorthandOptions, handler: RequestHandler)
Qué hace: Registra un manejador para solicitudes HTTP POST. Analiza automáticamente el cuerpo de la solicitud (JSON, form-data, etc.).
fastify.post('/user', async (request, reply) => {
const { name, email } = request.body;
// Guardamos el usuario en la BD...
return { status: 'created', name, email };
});
4.3. fastify.register(plugin, opts)
Firma: fastify.register(plugin: FastifyPluginAsync | FastifyPluginCallback, opts?: object)
Qué hace: Registra un plugin en la instancia de Fastify. Los plugins permiten encapsular funcionalidades (rutas, decoradores, hooks) y reutilizarlas en diferentes partes de la aplicación.
// plugins/routes.js
async function routes(fastify, options) {
fastify.get('/plugin', async (request, reply) => {
return { message: '¡Hola desde el plugin!' };
});
}
// server.js
fastify.register(routes);
4.4. fastify.listen(options)
Firma: fastify.listen(options: ListenOptions | string | number): Promise
Qué hace: Inicia el servidor HTTP y lo pone a escuchar en el puerto y host especificados. Devuelve una promesa que se resuelve con la dirección del servidor.
await fastify.listen({ port: 3000, host: '0.0.0.0' });
// También se puede pasar solo el puerto:
// await fastify.listen(3000);
4.5. fastify.addHook(name, hook)
Firma: fastify.addHook(name: string, hook: HookHandlerFunction)
Qué hace: Añade un hook (gancho) que se ejecuta en puntos específicos del ciclo de vida de la solicitud. Los hooks más comunes son onRequest, preHandler, onSend y onResponse.
// Hook que se ejecuta antes de cada solicitud
fastify.addHook('onRequest', async (request, reply) => {
console.log(`Solicitud recibida: ${request.method} ${request.url}`);
});
// Hook que se ejecuta antes del manejador de la ruta
fastify.addHook('preHandler', async (request, reply) => {
// Verificar autenticación, etc.
});
4.6. fastify.decorate(name, value)
Firma: fastify.decorate(name: string, value: any)
Qué hace: Añade una propiedad o método personalizado a la instancia de Fastify, haciéndolo accesible desde cualquier ruta o plugin.
// Añadimos un helper para respuestas estandarizadas
fastify.decorate('respond', function(data, statusCode = 200) {
return { status: 'success', data, timestamp: Date.now() };
});
// Uso en una ruta
fastify.get('/items', async (request, reply) => {
const items = ['item1', 'item2'];
return fastify.respond(items);
});
4.7. fastify.setErrorHandler(handler)
Firma: fastify.setErrorHandler(handler: ErrorHandler)
Qué hace: Define un manejador global de errores para capturar y personalizar las respuestas de error en toda la aplicación.
fastify.setErrorHandler(async (error, request, reply) => {
reply.status(error.statusCode || 500);
return {
error: true,
message: error.message || 'Error interno del servidor'
};
});
5. Ejemplo completo: API REST de tareas
Este ejemplo combina varios métodos de Fastify para crear una API REST funcional de gestión de tareas (CRUD).
// app.js
const fastify = require('fastify')({ logger: true });
// Almacenamiento en memoria (simula una base de datos)
let tasks = [
{ id: 1, title: 'Aprender Fastify', completed: false },
{ id: 2, title: 'Crear una API', completed: true }
];
let nextId = 3;
// Obtener todas las tareas
fastify.get('/tasks', async (request, reply) => {
return { tasks };
});
// Obtener una tarea por ID
fastify.get('/tasks/:id', async (request, reply) => {
const { id } = request.params;
const task = tasks.find(t => t.id === Number(id));
if (!task) {
reply.status(404);
return { error: 'Tarea no encontrada' };
}
return { task };
});
// Crear una nueva tarea
fastify.post('/tasks', async (request, reply) => {
const { title } = request.body;
if (!title) {
reply.status(400);
return { error: 'El título es obligatorio' };
}
const newTask = { id: nextId++, title, completed: false };
tasks.push(newTask);
reply.status(201);
return { task: newTask };
});
// Actualizar una tarea existente
fastify.put('/tasks/:id', async (request, reply) => {
const { id } = request.params;
const { title, completed } = request.body;
const task = tasks.find(t => t.id === Number(id));
if (!task) {
reply.status(404);
return { error: 'Tarea no encontrada' };
}
if (title !== undefined) task.title = title;
if (completed !== undefined) task.completed = completed;
return { task };
});
// Eliminar una tarea
fastify.delete('/tasks/:id', async (request, reply) => {
const { id } = request.params;
const index = tasks.findIndex(t => t.id === Number(id));
if (index === -1) {
reply.status(404);
return { error: 'Tarea no encontrada' };
}
tasks.splice(index, 1);
return { message: 'Tarea eliminada correctamente' };
});
// Iniciar el servidor
const start = async () => {
try {
await fastify.listen({ port: 3000 });
console.log('API de tareas disponible en http://localhost:3000');
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();
6. Conclusión
Fastify es una excelente opción para desarrollar aplicaciones web y APIs en Node.js, especialmente cuando se requiere alto rendimiento y baja latencia. Su ecosistema de plugins, su soporte para TypeScript y su facilidad de uso lo hacen adecuado tanto para proyectos pequeños como para sistemas empresariales complejos.
Si vienes de Express, notarás que Fastify tiene una curva de aprendizaje similar, pero ofrece mejoras significativas en velocidad y funcionalidades integradas. Te recomendamos explorar la documentación oficial y probarlo en tu próximo proyecto.