$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 server— Create 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 schema— Define 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 integration— Type-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 plugin— Encapsulated 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 — auth— Pre-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 parser— Custom body parsing.
app.addContentTypeParser('application/csv', { parseAs: 'string' }, (req, body, done) => {
done(null, parseCSV(body as string))
})Performance
Graceful shutdown— Clean server stop.
const signals = ['SIGINT', 'SIGTERM']
for (const signal of signals) {
process.on(signal, async () => {
await app.close()
process.exit(0)
})
}