Just Return a Value — Fastify Sends It
Async Handlers
An async handler can return a value that becomes the JSON body, or throw an error that Fastify maps to an HTTP status.
What you'll learn
- Return a value to send a 200 with JSON
- Throw to surface an error response
- Use httpErrors helpers for proper status codes
In Fastify, the simplest handler is an async function that returns the response body. No
res.json(...) calls; the framework handles serialization and status codes.
Return a Value
app.get('/posts/:id', async (req) => {
const post = await db.posts.find(req.params.id);
if (!post) throw app.httpErrors.notFound('Post not found');
return post;
}); If the handler resolves with a value, Fastify sends 200 OK with the JSON-serialized payload.
If it throws, the error flows into Fastify’s error handler.
Throw to Error
The @fastify/sensible plugin adds a httpErrors helper:
await app.register(import('@fastify/sensible'));
app.get('/secret', async (req) => {
if (!req.headers.authorization) {
throw app.httpErrors.unauthorized('Missing token');
}
return { ok: true };
}); Each helper sets the correct status and message: badRequest, unauthorized, forbidden,
notFound, conflict, internalServerError, and more.
Mixing Return and Reply
You can use reply.code(...) alongside returning a value:
app.post('/users', async (req, reply) => {
const user = await db.users.create(req.body);
reply.code(201);
return user;
}); Do not call both reply.send(...) and return value in the same async handler — pick one or
Fastify will warn about a double send.