Fastify is a framework for backend web development with a powerful plugin architecture and the least overhead. It’s primarily inspired by Hapi and Express and is one of the fastest web frameworks running on Node.js.
Fastify v3.0 is the latest version and has been available since early July 2020. Version 3 has some exceptional new functionalities such as:
- Running an Express application inside Fastify
- Changes in logging serialization
- Changes in schema substitution
- Better TypeScript support
An overview of Fastify’s features
Now that we’ve covered Fastify’s latest version update functionalities, let’s review a shortlist of Fastify’s most important features:
High performance
Depending on code complexity, it can serve around 30,000 requests per second or more for less complex business logic
Extendibility
Hooks, plugins, and decorators make it fully extensible
Scheme-based
Internally, Fastify compiles a JSON schema to a highly performant function that can be used for route validation and output serialization
Logging
Pino is a highly cost-effective logger used for faster logging
Developer-friendly environment
The framework is expressive and easy to get started with. Furthermore, it allows developers to quickly scale small projects to larger performant applications without sacrificing performance or security
TypeScript-ready
The TypeScript type declaration file maintains support to the TypeScript community
5 important Fastify plugins you should know
Besides the vast amount of features that Fastify offers, it also has a strong plugin architecture. Any developer can build plugins that work with Fastify to create quick building blocks for bootstrapping your API project.
Plugins developed by external developers fall under the category of “community plugins,” while the Fastify team also maintains some plugins of their own, which they label as “core plugins.” However, it’s important to know that any community plugin must adhere to Fastify’s best practices.
The benefit of using core plugins is that the Fastify team actively maintains those plugins, but keep in mind that community plugins may not be maintained.
Here are some important Fastify plugins to note:
- fastify-auth: An authentication plugin developed by the Fastify team that allows you to quickly inject authentication logic to your API routes
- fastify-cors: Cross-origin requests are important for any application, and fastify-cors helps you manage this without the need for installing a CORS package separately
- fastify-jwt: This plugin will decorate your application with standard JSON web token. Fastify-jwt internally uses the jsonwebtoken package
- fastify-nextjs: Next is a React framework for building pre-rendering websites at the server-side. This plugin helps you do the same with Fastify
- fastify-redis: This enables your Fastify application to share the same Redis connection throughout the server
And that’s not even a comprehensive list. Fastify has a wide range of plugins to choose from.
Fastify vs Koa vs Express
Each framework, of course, has its pros and cons — but each framework also has its application. It’s not easy to compare diverse frameworks. However, I tried to select relevant evaluation criteria for when you are choosing a framework.
Speed comparison
Here’s an overview of the speed comparison by StackShare.io.
Express: Express processes the least amount of request/sec. The benchmark proves that Express can handle 15,978 requests/sec
Koa: Koa is a better option than Express. It’s also a lightweight framework that handles 54,848 requests/sec
Fastify: Fastify received the best benchmark results with 78,956 requests/sec
Plugins ecosystem
As discussed in the previous section, Fastify is the only web framework of these three that has a wide range of plugins, and it makes a major difference. It’s a big plus for developers because they don’t have to rely on multiple frameworks or packages to build their applications. Fastify becomes the one-stop solution.
TypeScript support
Again, Fastify is the only framework that has TypeScript support out of the box. Depending on your Node.js version, you may need to install @types/node
.
Creating your first server with Fastify 3.0
And now, the exciting part! This tutorial will guide you through building your first server with Fastify, covering the following aspects:
- Installation
- Run your first server
- Add routes to your API
- Use Fastify plugins
- Add data validation capabilities
Ready? Let’s begin.
1. Installation and requirements
First, start a new npm project using:
npm init -y
Next, let’s add the Fastify dependency to your project.
Using npm:
npm i fastify --save
Using yarn:
yarn add fastify
Make sure to have the latest Node.js version installed on your system. You can use nvm (Node Version Manager) for quickly switching between different Node.js versions. You’ll also need a tool to send requests such as cURL or Postman.
2. Create server.js
Next, let’s create a new file called server.js
in the root of your project. Add the following code to your server.js
file:
const fastify = require('fastify')({ logger: true }) //Add routes here, discussed in further steps //@Server fastify.listen(5000, (err) => { if (err) { console.log(err) process.exit(1) } else { console.log(`Server running, navigate to https://localhost:5000`) } })
As you can see, the listen function starts the server on port 5000
. It also accepts a callback that accepts one argument, which can contain an error object. This is the most basic server setup for running a Fastify API.
If you want to try out this basic setup, you can use the node
command to run the server.js
file like this:
node server.js
This will start your server on the address http://localhost:5000. If you try navigating to the address, you’ll see an error that this route doesn’t exist because we haven’t defined any routes yet. Now we’ll need to add some simple CRUD routes.
3. Adding CRUD routes
Let’s add some basic CRUD routes to our application. First, let’s add a GET route.
3.1 GET route
Imagine we have a stack object that’s a type array. First, we want to add a GET route to retrieve the contents of this array. To do so, we can use the Fastify object to define a get
route. The first argument accepts the path we want to attach our route to and the second argument accepts a callback that sends back a reply to your client.
const stack = [] //@Routes fastify.get('/getStack', (request, reply) => { reply.send(stack) })
3.2 POST route
Next, let’s try adding items to our stack array using a POST route. This way, we can send data with our request. Here we expect the user to send a JSON object with one parameter called item
. We push this item
to our stack array. Now we can use the first argument of the callback request
, which contains the data being sent with the POST request.
fastify.post('/addItem', (request, reply) => { const item = request.body.item stack.push(item) reply.send(stack) })
The same principles apply for other route methods such as PUT, DELETE, HEAD, PATCH, and OPTIONS. More information about route options can be found in the Fastify documentation.
3.3 Final routing code
Your final routing code should look like this:
const fastify = require('fastify')({ logger: true }) const stack = [] //@Routes fastify.get('/getStack', (request, reply) => { reply.send(stack) }) fastify.post('/addItem', (request, reply) => { const item = request.body.item stack.push(item) reply.send(stack) }) //@Server fastify.listen(5000, (err) => { if (err) { console.log(err) process.exit(1) } else { console.log(`Server running, navigate to https://localhost:5000`) } })
Now let’s try out the code we’ve created. First, start the server with node server.js
. Next, visit the following route http://localhost:5000/getStack, which should return an empty array object.
Let’s add an item to the stack using cURL. I want to add an apple to the stack. Therefore, I send a JSON object with key item
and value apple
.
More great articles from LogRocket:
- Don't miss a moment with The Replay, a curated newsletter from LogRocket
- Learn how LogRocket's Galileo cuts through the noise to proactively resolve issues in your app
- Use React's useEffect to optimize your application's performance
- Switch between multiple versions of Node
- Discover how to animate your React app with AnimXYZ
- Explore Tauri, a new framework for building binaries
- Advisory boards aren’t just for executives. Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
curl --header "Content-Type: application/json" --request POST --data '{"item": "apple"}' http://localhost:5000/addItem
If you visit http://localhost:5000/getStack again, you’ll notice that the stack array is populated with the apple
item.
All good? Let’s add a plugin!
4. Add a plugin to your Fastify API
To demonstrate how easy it is to add and use a Fastify plugin, let’s install fastify-routes, which enables us to retrieve a map of all registered routes with our Fastify instance.
First, install the Fastify-routes dependency from the CLI:
npm i fastify-routes
After installing the plugin, register the plugin by including it before you register any routes.
Here’s a snippet of the server.js
file that includes the fastify-routes
plugin. I’ve also added a console.log
statement that shows how you can use the plugin to return all registered routes.
const fastify = require('fastify')({ logger: true }) fastify.register(require('fastify-routes')) // Add and register plugin const stack = [] //@Routes fastify.get('/getStack', (request, reply) => { reply.send(stack) }) fastify.post('/addItem', (request, reply) => { const item = request.body.item stack.push(item) reply.send(stack) }) //@Server fastify.listen(5000, (err) => { console.log(fastify.routes) // Log all registered routes if (err) { console.log(err) process.exit(1) } else { console.log(`Server running, navigate to https://localhost:5000`) } })
Now when you start the server with node server.js
, your CLI prints all registered routes.
This plugin demonstrates how easy it is to add a plugin to your server. You don’t need to initialize them. The fastify
object that forms your server also acts as the parent for all the registered plugins, and you can call them directly from this fastify
object.
Finally, let’s add some basic data validation to our server.
5. Add data validation
As the final element in this tutorial, let’s add data validation to your routes. Specifically, we want to add validation for the POST route we created earlier. Let’s validate if the body object contains the item
property and the type of data should match a string
type.
Luckily, Fastify allows us to define validation schemas for routes. Here’s an example that verifies if the item
property is present and contains a string
. Furthermore, we tell the Fastify server that we don’t allow any additional properties on the body object using the additionalProperties: false
setting.
You can also define a response property that describes the response when the request is successful.
Here’s the full code after adding the data validation options. Do not forget to add the itemValidation
as the second argument to the POST route.
const fastify = require('fastify')({ logger: true }) fastify.register(require('fastify-routes')) const itemValidation = { // Define validation schema: { body: { type: 'object', additionalProperties: false, required: [ 'item' ], properties: { item: { type: 'string' } } }, response: { 201: { type: 'object', properties: { item: { type: 'string' } } } } } } const stack = [] //@Routes fastify.get('/getStack', (request, reply) => { reply.send(stack) }) fastify.post('/addItem', itemValidation, (request, reply) => { // Add validation options to POST route const item = request.body.item stack.push(item) reply.send(stack) }) //@Server fastify.listen(5000, (err) => { console.log(fastify.routes) if (err) { console.log(err) process.exit(1) } else { console.log(`Server running, navigate to https://localhost:5000`) } })
Let’s try out the code again by sending the same request to our server, adding the apple
item. This request should be successfully executed.
curl --header "Content-Type: application/json" --request POST --data '{"item": "apple"}' http://localhost:5000/addItem
Next, let’s try sending an item that contains an empty object so we can test if the server rejects the request. Send the below request to your server to verify the data validation implementation.
curl --header "Content-Type: application/json" --request POST --data '{"item": {}}' http://localhost:5000/addItem
The server should send you the following error message:
{"statusCode":400,"error":"Bad Request","message":"body.item should be string"}
All good? Congratulations! You’ve successfully completed your first Fastify API server.
Conclusion
I hope you enjoyed building a simple CRUD API using Fastify while implementing data validation and adding plugins.
Many more plugins exist, so definitely check out the Fastify plugin ecosystem to see what’s available. Plugins are useful to quickly bootstrap your API, removing the need to build an API from scratch.
Feel free to check out the following concepts Fastify offers:
- Data serialization
- How to use HTTP2 for your server
- Add hooks to listen for specific events in your server
- Need custom middleware? Just add it!
That’s it, folks! Full code can be found on my GitHub repository.
Get setup with LogRocket's modern error tracking in minutes:
- Visit https://logrocket.com/signup/ to get an app ID.
- Install LogRocket via NPM or script tag.
LogRocket.init()
must be called client-side, not server-side. - (Optional) Install plugins for deeper integrations with your stack:
- Redux middleware
- ngrx middleware
- Vuex plugin
$ npm i --save logrocket
// Code:
import LogRocket from 'logrocket';
LogRocket.init('app/id');
Add to your HTML:
<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>