Skip to main content
Version: v1.14.x



The Fastify module exports a factory function that is used to create new

Fastify serverinstances. This factory function accepts an options object which is used to customize the resulting instance. This document describes the properties available in that options object.

http2 (Status: experimental)

If true Node.js core's HTTP/2 module is used for binding the socket.

  • Default: false


An object used to configure the server's listening socket for TLS. The options are the same as the Node.js core createServer method. When this property is null, the socket will not be configured for TLS.

This option also applies when the

http2 option is set.
  • Default: null


Fastify uses find-my-way to handle routing. This option may be set to true to ignore trailing slashes in routes. This option applies to all route registrations for the resulting server instance.

  • Default: false
const fastify = require('fastify')({
ignoreTrailingSlash: true

// registers both "/foo" and "/foo/"
fastify.get('/foo/', function (req, reply) {

// registers both "/bar" and "/bar/"
fastify.get('/bar', function (req, reply) {


You can set a custom length for parameters in parametric (standard, regex and multi) routes by using maxParamLength option, the default value is 100 characters.
This can be useful especially if you have some regex based route, protecting you against DoS attacks.
If the maximum length limit is reached, the not found route will be invoked.


Defines the maximum payload, in bytes, the server is allowed to accept.

  • Default: 1048576 (1MiB)


Defines what action the framework must take when parsing a JSON object with __proto__. This functionality is provided by bourne. See for more details about prototype poisoning attacks.

Possible values are 'error', 'remove' and 'ignore'.

  • Default: 'error'


Fastify includes built-in logging via the Pino logger. This property is used to configure the internal logger instance.

The possible values this property may have are:

  • Default: false. The logger is disabled. All logging methods will point to a null logger abstract-logging instance.

  • pinoInstance: a previously instantiated instance of Pino. The internal logger will point to this instance.

  • object: a standard Pino options object. This will be passed directly to the Pino constructor. If the following properties are not present on the object, they will be added accordingly:

    * `genReqId`: a synchronous function that will be used to generate identifiers
    for incoming requests. The default function generates sequential identifiers.
    * `level`: the minimum logging level. If not set, it will be set to `'info'`.
    * `serializers`: a hash of serialization functions. By default, serializers
    are added for `req` (incoming request objects), `res` (outgoing repsonse
    objets), and `err` (standard `Error` objects). When a log method receives
    an object with any of these properties then the respective serializer will
    be used for that property. For example:

        fastify.get('/foo', function (req, res) {{req}) // log the serialized request object

  Any user supplied serializer will override the default serializer of the
corresponding property.


You can pass a custom http server to Fastify by using the serverFactory option.
serverFactory is a function that takes an handler parameter, which takes the request and response objects as parameters, and an options object, which is the same you have passed to Fastify.

const serverFactory = (handler, opts) => {
const server = http.createServer((req, res) => {
handler(req, res)

return server

const fastify = Fastify({ serverFactory })

fastify.get('/', (req, reply) => {
reply.send({ hello: 'world' })


Internally Fastify uses the API of Node core http server, so if you are using a custom server you must be sure to have the same API exposed. If not, you can enhance the server instance inside the serverFactory function before the return statement.


By default, value equal to true, routes are registered as case sensitive. That is, /foo is not equivalent to /Foo. When set to false, routes are registered in a fashion such that /foo is equivalent to /Foo which is equivalent to /FOO.

Setting caseSensitive to false will also result in all params (and all value matched by regexps) to be lowercased as well.

fastify.get('/user/:username', (request, reply) => {
// Given the URL: /user/NodeJS
console.log(request.params.username) // -> 'nodejs'

Please note this setting this option to false goes against RFC3986.


The header name used to know the request id. See the request id section.

  • Default: 'request-id'


By enabling the trustProxy option, Fastify will have knowledge that it's sitting behind a proxy and that the X-Forwarded-* header fields may be trusted, which otherwise may be easily spoofed.

const fastify = Fastify({ trustProxy: true })

  • Default: false
  • true/false: Trust all proxies (true) or do not trust any proxies (false).
  • string: Trust only given IP/CIDR (e.g. ''). May be a list of comma separated values (e.g. ',').
  • Array<string>: Trust only given IP/CIDR list (e.g. ['']).
  • number: Trust the nth hop from the front-facing proxy server as the client.
  • Function: Custom trust function that takes address as first arg
    function myTrustFn(address, hop) {
return address === '' || hop === 1

For more examples refer to proxy-addr package.

You may also access ip and hostname values from raw request.

fastify.get('/', (request, reply) => {


The maximum amount of time in milliseconds in which a plugin can load. If not, ready will complete with an Error with code 'ERR_AVVIO_PLUGIN_TIMEOUT'.

  • Default: 0 (disabled)


By default you can version your routes with semver versioning, which is provided by find-my-way. There is still an option to provide custom versioning strategy. You can find more information in the find-my-way documentation.

const versioning = {
storage: function () {
let versions = {}
return {
get: (version) => { return versions[version] || null },
set: (version, store) => { versions[version] = store },
del: (version) => { delete versions[version] },
empty: () => { versions = {} }
deriveVersion: (req, ctx) => {
return req.headers['accept']

const fastify = require('fastify')({


Server Methods


fastify.server: The Node core server object as returned by the Fastify factory function.


Invoked when the current plugin and all the plugins that have been registered within it have finished loading. It is always executed before the method fastify.ready.

.register((instance, opts, next) => {
console.log('Current plugin')
.after(err => {
console.log('After current plugin')
.register((instance, opts, next) => {
console.log('Next plugin')
.ready(err => {
console.log('Everything has been loaded')


Function called when all the plugins have been loaded. It takes an error parameter if something went wrong.

fastify.ready(err => {
if (err) throw err

If it is called without any arguments, it will return a Promise:

fastify.ready().then(() => {
console.log('successfully booted!')
}, (err) => {
console.log('an error happened', err)


Starts the server on the given port after all the plugins are loaded, internally waits for the .ready() event. The callback is the same as the Node core. By default, the server will listen on the address resolved by localhost when no specific address is provided ( or ::1 depending on the operating system). If listening on any available interface is desired, then specifying for the address will listen on all IPv4 address. Using :: for the address will listen on all IPv6 addresses, and, depending on OS, may also listen on all IPv4 addresses. Be careful when deciding to listen on all interfaces; it comes with inherent security risks.

fastify.listen(3000, (err, address) => {
if (err) {

Specifying an address is also supported:

fastify.listen(3000, '', (err, address) => {
if (err) {

Specifying a backlog queue size is also supported:

fastify.listen(3000, '', 511, (err, address) => {
if (err) {

If no callback is provided a Promise is returned:

.then((address) => console.log(`server listening on ${address}`))
.catch(err => {
console.log('Error starting server:', err)

Specifying an address without a callback is also supported:

fastify.listen(3000, '')
.then((address) => console.log(`server listening on ${address}`))
.catch(err => {
console.log('Error starting server:', err)

When deploying to a Docker, and potentially other, containers, it is advisable to listen on because they do not default to exposing mapped ports to localhost:

fastify.listen(3000, '', (err, address) => {
if (err) {

If the port is omitted (or is set to zero), a random available port is automatically chosen (later available via fastify.server.address().port).


Method to add routes to the server, it also has shorthand functions, check here.


fastify.close(callback): call this function to close the server instance and run the 'onClose' hook.
Calling close will also cause the server to respond to every new incoming request with a 503 error and destroy that request.


Function useful if you need to decorate the fastify instance, Reply or Request, check here.


Fastify allows the user to extend its functionality with plugins. A plugin can be a set of routes, a server decorator or whatever, check here.


Function to add middlewares to Fastify, check here.


Function to add a specific hook in the lifecycle of Fastify, check here.


The full path that will be prefixed to a route.


fastify.register(function (instance, opts, next) {
instance.get('/foo', function (request, reply) {
// Will log "basePath: /v1"'basePath: %s', instance.basePath)
reply.send({basePath: instance.basePath})

instance.register(function (instance, opts, next) {
instance.get('/bar', function (request, reply) {
// Will log "basePath: /v1/v2"'basePath: %s', instance.basePath)
reply.send({basePath: instance.basePath})

}, { prefix: '/v2' })

}, { prefix: '/v1' })


The logger instance, check here.


Fake http injection (for testing purposes) here.


fastify.addSchema(schemaObj), adds a shared schema to the Fastify instance. This allows you to reuse it everywhere in your application just by writing the schema id that you need.
To learn more, see shared schema example in the Validation and Serialization documentation.


Set the schema compiler for all routes here.


fastify.setNotFoundHandler(handler(request, reply)): set the 404 handler. This call is encapsulated by prefix, so different plugins can set different not found handlers if a different prefix option is passed to fastify.register(). The handler is treated like a regular route handler so requests will go through the full Fastify lifecycle.

You can also register beforeHandler hook for the 404 handler.

beforeHandler: (req, reply, next) => {
req.body.beforeHandler = true
}, function (request, reply) {
// Default not found handler with beforeHandler hook

fastify.register(function (instance, options, next) {
instance.setNotFoundHandler(function (request, reply) {
// Handle not found request without beforeHandler hook
// to URLs that begin with '/v1'
}, { prefix: '/v1' })


fastify.setErrorHandler(handler(error, request, reply)): Set a function that will be called whenever an error happens. The handler is fully encapsulated, so different plugins can set different error handlers. async-await is supported as well.

fastify.setErrorHandler(function (error, request, reply) {
// Send error response


fastify.printRoutes(): Prints the representation of the internal radix tree used by the router, useful for debugging.
Remember to call it inside or after a ready call.

fastify.get('/test', () => {})
fastify.get('/test/hello', () => {})
fastify.get('/hello/world', () => {})

fastify.ready(() => {
// └── /
// ├── test (GET)
// │ └── /hello (GET)
// └── hello/world (GET)