Skip to content
>_devvkit
$devvkit learn --librarie fastify-guide

Fastify Guide

[nodejs][http][server][performance]
JavaScript / TypeScript
Install
npm install fastify

Fastify is built for speed. Its schema-based serialization (using JSON Schema) is significantly faster than Express's runtime JSON.stringify. Benchmarks show 2-3x throughput over Express.

The plugin system provides encapsulation — each plugin has its own scope. Decorators extend the core request/reply objects. Hooks (onRequest, preHandler, onSend) replace Express middleware chains.

Fastify 5 supports TypeScript natively. The logger (Pino) is the fastest Node.js logger. Validation via @fastify/type-provider-typebox integrates with TypeScript types.

Setup

Basic serverCreate Fastify app.
import Fastify from 'fastify'

const app = Fastify({ logger: true })

app.get('/', async (req, reply) => {
  return { hello: 'world' }
})

app.listen({ port: 3000 })

Schemas & Validation

Route with schemaDefine JSON Schema for validation.
app.get('/users/:id', {
  schema: {
    params: { type: 'object', properties: { id: { type: 'integer' } } },
    response: { 200: { type: 'object', properties: { id: { type: 'integer' }, name: { type: 'string' } } } },
  },
}, async (req) => {
  return db.findUser(req.params.id)
})
TypeBox integrationType-safe schemas.
import { Type, TypeBoxTypeProvider } from '@fastify/type-provider-typebox'

const app = Fastify().withTypeProvider<TypeBoxTypeProvider>()

app.get('/users/:id', {
  schema: {
    params: Type.Object({ id: Type.Number() }),
    response: { 200: Type.Object({ id: Type.Number(), name: Type.String() }) },
  },
}, async (req) => db.findUser(req.params.id))

Plugins

Register pluginEncapsulated plugin.
import fp from 'fastify-plugin'

export default fp(async function dbPlugin(app, opts) {
  app.decorate('db', {
    getUsers: () => fetch('/api/users').then(r => r.json()),
  })
})

// In app:
app.register(dbPlugin)
app.get('/users', async (req) => app.db.getUsers())

Hooks

Hook — authPre-handler for auth.
app.addHook('preHandler', async (req, reply) => {
  const token = req.headers.authorization
  if (!token) return reply.status(401).send({ error: 'Unauthorized' })
  req.user = await verifyToken(token)
})
Content type parserCustom body parsing.
app.addContentTypeParser('application/csv', { parseAs: 'string' }, (req, body, done) => {
  done(null, parseCSV(body as string))
})

Performance

Graceful shutdownClean server stop.
const signals = ['SIGINT', 'SIGTERM']
for (const signal of signals) {
  process.on(signal, async () => {
    await app.close()
    process.exit(0)
  })
}