Lifecycle Hooks
// Order of execution:\n// onRequest -> preParsing -> preValidation -> preHandler\n// -> handler -> preSerialization -> onSend -> onResponse\n\napp.addHook('onRequest', async (request, reply) => {\n // Runs before any parsing\n console.log('Incoming request:', request.method, request.url);\n});\n\napp.addHook('preHandler', async (request, reply) => {\n // Runs after validation, before handler\n request.startTime = Date.now();\n});\n\napp.addHook('onResponse', async (request, reply) => {\n // Runs after response is sent\n const duration = Date.now() - request.startTime;\n console.log(`Response sent in ${duration}ms`);\n});\n\n// Reply methods\nreply.code(201); // Set status code\nreply.header('X-Custom', 'value'); // Set header\nreply.send({ data: 'hello' }); // Send JSON\nreply.type('application/json'); // Set Content-Type\nreply.redirect('/login'); // Redirect\nreply.view('/template', data); // Render template (with @fastify/view)
Error Handling
// Global error handler\napp.setErrorHandler((error, request, reply) => {\n app.log.error(error);\n \n const statusCode = error.statusCode || 500;\n const message = statusCode === 500 ? 'Internal Server Error' : error.message;\n \n reply.code(statusCode).send({\n error: message,\n statusCode,\n });\n});\n\n// Not found handler\napp.setNotFoundHandler((request, reply) => {\n reply.code(404).send({\n error: 'Route not found',\n method: request.method,\n url: request.url,\n });\n});
Examples
const Fastify = require('fastify');
const app = Fastify({ logger: true });
// Timing hook
app.addHook('onRequest', async (request) => {
request.startTime = Date.now();
});
app.addHook('onResponse', async (request, reply) => {
const ms = Date.now() - request.startTime;
app.log.info({ url: request.url, ms }, 'Request completed');
});
// Custom error handler
app.setErrorHandler((error, request, reply) => {
const statusCode = error.statusCode || 500;
app.log.error({ err: error, statusCode }, 'Request error');
reply.code(statusCode).send({
success: false,
error: statusCode === 500 ? 'Internal error' : error.message,
...(process.env.NODE_ENV === 'development' && { stack: error.stack }),
});
});
app.setNotFoundHandler((request, reply) => {
reply.code(404).send({ success: false, error: 'Route not found' });
});
app.get('/ok', async () => ({ success: true }));
app.get('/throw', async () => { throw new Error('test error'); });
app.listen({ port: 3000 });