Let's learn Fastify.js - A Fast and low overhead web framework, for Node.js

Let's learn Fastify.js - A Fast and low overhead web framework, for Node.js

Written : 2022-09-13 Last Update : 2022-09-13

What is fastify

According to the website itself, 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.

It is another node js powered server side framework, which is good enough to be considered.

Why fastify

Fastify promotes itself by some really good points that will help us understand, why we can use this.

  1. Fast and low overhead web framework.

  2. Like express js but faster than express js.

  3. A better way to use plugins.

  4. Straight forward for APIs development, although can be used for SSR.

  5. A Better Request and response validation.

Other Options

There are many other options available for creating a web server using node.js

  1. Express js
  2. Fastify js
  3. Nest js
  4. Koa

But when it comes to developing API, fastify could be a very good option as it provides a clean architecture and default validation for request and responses.

See the pro and cons of some top nodejs web frameworks here (opens in a new tab).

Express vs Fastify

A common question may arise that why would you use fastify when there is express already. Fastify wins this argument by it's benchmarks. Fastify benchmarks (opens in a new tab)

Fastify has a logger included, so I don't have to think about how to log.

Fastify supports async/await out of the box for all the components that must be awaited.

Another reason is that fastify provides some core plugins for which express js has to rely on the community.

Getting Started

We simply create a node js project, and install fastify in it.

mkdir fastify_started
cd fastify_started
npm init --yes
npm i fastify

Simple Server

A simple fastify server to saay hello world is almost similiar to an express server doing the same.

We create an index.js file to write server code.

touch index.js
const fastify = require('fastify');
const app = fastify();
 
app.get('/', (req, res) => {
    res.send("Hello World !");
});
 
const PORT = 5000;
app.listen(PORT, () => {
    console.log("Server Started !")
});

The code is as simple as it looks. We create a app from fastify.

When a get request is made at / route, we simply send hello world.

We use a port variable and make the app listen to the particular port.

Routing

Let's see how we can handle different Request methods using fastify. I think the code itself is pretty self explanatory.

const fastify = require('fastify');
const app = fastify();
 
app.get('/', (req, res) => {
    res.send("Hello World !");
});
 
app.post('/', (req, res) => {
    res.send("Hello POST !");
});
 
app.delete('/', (req, res) => {
    res.send("Hello DELETE !");
});
 
app.put('/', (req, res) => {
    res.send("Hello PUT !");
});
 
app.all('/user', (req, res) => {
    res.send("Hello All !");
});
 
const PORT = 5000;
app.listen(PORT, () => {
    console.log("Server Started !")
});

Router / Controller

It's a good idea to handle all the routes in different files or via a controller. it's a good way to maintain clean code and good architecture. Create an router.js file in controllers directory in the root folder. In our index.js file, we will register a router.

// register the router from controller to handle routes
app.register(require('./controllers/router'));

In the router.js file we will add a simpel router function to handle the routes.

function Router(app, options, done) {
    // @Routes
    app.get('/', (req, res) => {
        res.code(200).send({"data" : "Response from router !"});
    }); 
 
    // @Not-Found Route
    app.all('*', (req, reply) => reply.code(404).send("ERR ! Not Found !"));
 
    done();
};
 
module.exports = Router;

Notice that things are little different here from express.js. Instead of use, we are using register and the router function ends with done(), just like a middleware in express js.

Route Prefix

Adding a route prefix is as simple as the below code.

It adds a /api/v1 to all the routes the router.

app.register(require('./controllers/router'), { prefix: 'api/v1' });

Query Parameters

All the query parameters are available in req.query. Let's take a look at a simple example.

// query
app.get('/user', (req, res) => {
    res.code(200).send({"data" : req.query.name});
}); 

If we send a name query with data, we will get the following resposne.

localhost:5000/user?name=Desi Programmer
{
  "data": "Desi Programmer"
}

Url Parameters

Url Parameters are available in req.params Let's take a look at a simple example.

app.get('/user/:username', (req, res) => {
    res.code(200).send({"data" : req.params.username});
});
localhost:5000/user/Desi Programmer
{
  "data": "Desi Programmer"
}

The parameter here is mandatory, which means without a parameter value, the route will throw an error. If we add a ? then the parameter becomes optional.

app.get('/user/:username?', (req, res) => {
    res.code(200).send({"data" : req.params.username});
});

Body

Handling body data is pretty easy in fastify as it securely parses the json by default.

That's why I said Straight forward for APIs development.

app.post('/', (req, res) => {
    res.code(200).send({"name" : req.body.name, "data" : req.body});
}); 

Make a request with name in json data and you will get the value in response.

  • Request
localhost:5000/
  • Body
{
	"name" : "Desi Programmer",
	"username" : "Desi Programmer"
}
  • Response
{
	"name": "Desi Programmer",
	"data": {
		"name": "Desi Programmer",
		"username": "Desi Programmer"
	}
}