Fast and low overhead web framework, for Node.js

Why

An efficient server implies a lower cost of the infrastructure, a better responsiveness under load and happy users. How can you efficiently handle the resources of your server, knowing that you are serving the highest number of requests possible, without sacrificing security validations and handy development?

Enter Fastify. Fastify is a web framework highly focused on providing the best developer experience with the least overhead and a powerful plugin architecture, inspired by Hapi and Express. As far as we know, it is one of the fastest web frameworks in town.

Who is using Fastify?

Fastify is proudly powering a large ecosystem of organisations and products out there.

Discover more organisations using Fastify. Do you want your organisation to be featured here?

  • UrbanPiper is using Fastify
  • Compressor is using Fastify
  • Seznam.cz is using Fastify
  • Beliven is using Fastify
  • Jochen Schweizer is using Fastify
  • Monitr is using Fastify
  • CorsairM360 is using Fastify
  • UNIQ is using Fastify
  • car2go is using Fastify
  • LogDNA is using Fastify
  • Chatlayer by Sinch is using Fastify
  • Unhandled is using Fastify

Core features

These are the main features and principles on which fastify has been built:

  • Highly performant: as far as we know, Fastify is one of the fastest web frameworks in town, depending on the code complexity we can serve up to 30 thousand requests per second.
  • Extensible: Fastify is fully extensible via its hooks, plugins and decorators.
  • Schema based: even if it is not mandatory we recommend to use JSON Schema to validate your routes and serialize your outputs, internally Fastify compiles the schema in a highly performant function.
  • Logging: logs are extremely important but are costly; we chose the best logger to almost remove this cost, Pino!
  • Developer friendly: the framework is built to be very expressive and to help developers in their daily use, without sacrificing performance and security.
  • TypeScript ready: we work hard to maintain a TypeScript type declaration file so we can support the growing TypeScript community.

Quick start

Get fastify with NPM:

npm install fastify

Then create server.js and add the following content:

// Require the framework and instantiate it
const fastify = require('fastify')({ logger: true })

// Declare a route
fastify.get('/', (request, reply) => {
  reply.send({ hello: 'world' })
})

// Run the server!
fastify.listen({ port: 3000 }, (err) => {
  if (err) {
    fastify.log.error(err)
    process.exit(1)
  }
})
// Require the framework and instantiate it
const fastify = require('fastify')({ logger: true })

// Declare a route
fastify.get('/', async (request, reply) => {
  return { hello: 'world' }
})

// Run the server!
const start = async () => {
  try {
    await fastify.listen({ port: 3000 })
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}
start()

Finally, launch the server with:

node server

and you can test it with:

curl http://localhost:3000

Using CLI

Get fastify-cli with NPM:

npm install --global fastify-cli

Then scaffold a new project with:

fastify generate myproject

Request/Response validation and hooks

Of course, Fastify can do much more than this.

For example, you can easily provide input and output validation using JSON Schema and perform specific operations before the handler is executed:

const fastify = require('fastify')({ logger: true })

fastify.route({
  method: 'GET',
  url: '/',
  schema: {
    // request needs to have a querystring with a `name` parameter
    querystring: {
      type: 'object',
      properties: {
          name: { type: 'string'}
      },
      required: ['name'],
    },
    // the response needs to be an object with an `hello` property of type 'string'
    response: {
      200: {
        type: 'object',
        properties: {
          hello: { type: 'string' }
        }
      }
    }
  },
  // this function is executed for every request before the handler is executed
  preHandler: (request, reply, done) => {
    // E.g. check authentication
    done()
  },
  handler: (request, reply) => {
    reply.send({ hello: 'world' })
  }
})

fastify.listen({ port: 3000 }, (err) => {
  if (err) {
    fastify.log.error(err)
    process.exit(1)
  }
})
const fastify = require('fastify')({ logger: true })

fastify.route({
  method: 'GET',
  url: '/',
  schema: {
    // request needs to have a querystring with a `name` parameter
    querystring: {
      type: 'object',
      properties: {
          name: { type: 'string'}
      },
      required: ['name'],
    },
    // the response needs to be an object with an `hello` property of type 'string'
    response: {
      200: {
        type: 'object',
        properties: {
          hello: { type: 'string' }
        }
      }
    }
  },
  // this function is executed for every request before the handler is executed
  preHandler: async (request, reply) => {
    // E.g. check authentication
  },
  handler: async (request, reply) => {
    return { hello: 'world' }
  }
})

const start = async () => {
  try {
    await fastify.listen({ port: 3000 })
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}
start()

TypeScript Support

Fastify is shipped with a typings file, but you may need to install @types/node, depending on the Node.js version you are using.

The following example creates a http server.

We pass the relevant typings for our http version used.

By passing types we get correctly typed access to the underlying http objects in routes.

If using http2 we'd pass <http2.Http2Server, http2.Http2ServerRequest, http2.Http2ServerResponse>.

For https pass http2.Http2SecureServer or http.SecureServer instead of Server.

This ensures within the server handler we also get http.ServerResponse with correct typings on reply.res.

import Fastify, { FastifyInstance, RouteShorthandOptions } from 'fastify'
import { Server, IncomingMessage, ServerResponse } from 'http'

const server: FastifyInstance = Fastify({})

const opts: RouteShorthandOptions = {
  schema: {
    response: {
      200: {
        type: 'object',
        properties: {
          pong: {
            type: 'string'
          }
        }
      }
    }
  }
}

server.get('/ping', opts, (request, reply) => {
  reply.send({ pong: 'it worked!' })
})

server.listen({ port: 3000 }, (err) => {
  if (err) {
    server.log.error(err)
    process.exit(1)
  }

  const address = server.server.address()
  const port = typeof address === 'string' ? address : address?.port

})
import Fastify, { FastifyInstance, RouteShorthandOptions } from 'fastify'
import { Server, IncomingMessage, ServerResponse } from 'http'

const server: FastifyInstance = Fastify({})

const opts: RouteShorthandOptions = {
  schema: {
    response: {
      200: {
        type: 'object',
        properties: {
          pong: {
            type: 'string'
          }
        }
      }
    }
  }
}

server.get('/ping', opts, async (request, reply) => {
  return { pong: 'it worked!' }
})

const start = async () => {
  try {
    await server.listen({ port: 3000 })

    const address = server.server.address()
    const port = typeof address === 'string' ? address : address?.port

  } catch (err) {
    server.log.error(err)
    process.exit(1)
  }
}
start()

Visit the Documentation to learn more about all the features that Fastify has to offer.

A fast web framework

Leveraging our experience with Node.js performance, Fastify has been built from the ground up to be as fast as possible. Have a look at our benchmarks section to compare fastify performance to other common web frameworks.

Ecosystem

Fastify has an ever-growing ecosystem of plugins. Probably there is already a plugin for your favourite database or template language. Have a look at the Ecosystem page to navigate through the currently available plugins. Can't you find the plugin you are looking for? No problem, it's very easy to write one!

The team

In alphabetical order

Lead Maintainers

Matteo Collina's profile picture

Matteo Collina

Tomas Della Vedova's profile picture

Tomas Della Vedova

Collaborators

Tommaso Allevi's profile picture

Tommaso Allevi

Ayoub El Khattabi's profile picture

Ayoub El Khattabi

David Clements's profile picture

David Clements

Dustin Deus's profile picture

Dustin Deus

Carlos Fuentes's profile picture

Carlos Fuentes

Rafael Gonzaga's profile picture

Rafael Gonzaga

Vincent Le Goff's profile picture

Vincent Le Goff

Luciano Mammino's profile picture

Luciano Mammino

Salman Mitha's profile picture

Salman Mitha

Igor Savin's profile picture

Igor Savin

Evan Shortiss's profile picture

Evan Shortiss

Maksim Sinik's profile picture

Maksim Sinik

Frazer Smith's profile picture

Frazer Smith

Manuel Spigolon's profile picture

Manuel Spigolon

James Sumners's profile picture

James Sumners

Past Collaborators

Ethan Arrowood's profile picture

Ethan Arrowood

Cemre Mengu's profile picture

Cemre Mengu

Trivikram Kamat's profile picture

Trivikram Kamat

Nathan Woltman's profile picture

Nathan Woltman

Çağatay Çalı's profile picture

Çağatay Çalı

Acknowledgments

This project is kindly sponsored by:

Past Sponsors:

Also thanks to:

Hosted by

We are an At Large project at the OpenJS Foundation.