Technology
17
minutes read

What is Fastify? A complete guide on lightning-fast Node.js plugin

Written by
Zuzanna Olszewska
Published on
October 17, 2023
TL;DR

In the bustling world of web development, Fastify stands out as a game-changing framework for Node.js, favored by 60% of developers. Thanks to its robust plugin architecture, it excels in creating high-speed HTTP APIs with minimal effort. Read to learn about Fastify's unique features and why it's rapidly becoming the go-to choice for efficient, secure web development solutions.

Author
Zuzanna Olszewska
Frontend Developer
My LinkedIn
Download 2024 SaaS Report
By subscribing you agree to our Privacy Policy.
Thank you! Your submission has been received
Oops! Something went wrong while submitting the form.
Share

Fastify - the speed demon of web frameworks

Web frameworks simplify development by offering high-level APIs for abstract access to system resources. In the current web landscape, 60% of developers opt for client-side or server-side frameworks. Java, with its array of frameworks, stands out as a significant contender. 

Frameworks like Express facilitate API creation with Node.js, but they have limitations. Addressing these, Java introduced Fastify for precise and efficient solutions. 

Let's explore Fastify's key features and understand why it's gaining rapid popularity!

What is Fastify?

Fastify, being a cutting-edge framework for Node.js, redefines the web development experience. The reason behind its smooth working is a robust plugin architecture. Inspired by Hapi, Restify, and Express, Fastify.js stands out as a versatile solution for web development needs. 

Fastify node.js is not just another framework. Rather, it excels in crafting high-speed HTTP API and uses JSON as the data format. Being highly efficient, Fastify.js allows developers to create lightning-fast APIs with minimal effort. Developers then test these APIs with Java by setting up a Fastify server, defining routes, and then using a Java HTTP client to interact with those routes.

Moreover, it prioritizes maximizing server resources. It also handles a large number of requests without compromising on number of resources. Without a doubt, the Fastify framework is a go-to choice for developers seeking a resource-efficient framework that also maintains crucial elements like security and convenient development. 

Core features of Fastify – a Node.js framework

Fastify.js is a fast and flexible server-side templating engine. It supports all of the features you’d expect from a full-featured templating engine:

1. Efficient routing

Fastify routes data through a central router. This router translates requests into HTTP requests and routes them to the appropriate handler. Pure JavaScript implements this router and does not require any external dependencies on third-party services or libraries. This way, Fastify APIs run in Node or any browser that doesn’t support routing.  

2. Schema-based validation

Fastify APIs validate request schemas against built-in schemas as well as custom ones provided by plugins. Built-in schemas are used for common data types like integers or strings; custom schemas can extend this by defining additional validation rules. 

The schema validation process is asynchronous, so the app can continue to serve requests while validating them without blocking other parts of the application.

3. Extensibility through hooks

Hooks in the Fastify framework provide specific entry points in the application lifecycle where developers can inject custom logic. This enables developers to extend and customize Fastify’s behavior. Moreover, this flexibility enables developers to intervene at crucial stages, ensuring a seamless integration of tailored solutions and the incorporation of additional functionalities. 

This not only promotes a high level of customization but also contributes to the adaptability and versatility of Fastify node.js for a diverse range of web development scenarios. 

4. Powerful plugin architecture

The core of Fastify working is its robust plugin architecture that offers a powerful mechanism for enhancing the framework’s functionality. The developers can integrate plugins seamlessly and can encapsulate specific features with modern modular units. 

This way, developers can access a clean and organized code structure. Additionally, this plugin architecture facilitates a scalable development process that encourages the creation of modular components that can be reused easily. This modern development practice makes Fastify an ideal choice for building dynamic and feature-rich web applications. 

5. Fast HTTP API development

Fastify makes it easy to build RESTful APIs with minimal overhead. The Fastify HTTP API module provides an HTTP adapter that allows you to use standard request/response patterns in your application code without any changes to your application logic or configuration.

Fastify vs. express

Here’s an overview of Fastify vs. Express. 

Criteria

Fastify

Express

Focus

Prioritizes minimalism and speed, focusing on efficient APIs.

Embraces flexibility and a more comprehensive approach.

Speed And Scalability

78,956 requests per second

15,978 requests per second

TypeScript Support

Supported (Dependent on Node.js)

Challenges in providing seamless support

Plugins Availability

Extensive plugins available

Limited Plugins

Learning Curve

Straightforward, minimal learning

A steeper learning curve due to more

curve, suitable for beginners.

Community Support

Growing community, active support, and regular updates.

Established a large community with a wealth of resources.

Flexibility

Offers flexibility but is more opinionated for better performance.

Highly flexible, allowing developers to choose their preferred architecture.

Use Cases

Ideal for developing efficient APIs, especially when performance is key. 

Versatile and suitable for a wide range of applications, including web servers, APIs, and single-page applications.

Five significant fastify plugins

Let's explore 5 major plugins to enhance the working of Fastify:

1. fastify-swagger

Fastify-swagger generates Swagger/OpenAPI documentation for your Fastify APIs, making it easier to understand and interact with your API.

2. fastify-jwt

Fastify-jwt adds JSON Web Token (JWT) authentication support to Fastify, allowing you to secure your routes with token-based authentication.

3. fastify-multipart

Fastify-multipart enables handling multipart/form-data requests, making it useful for working with file uploads in your Fastify application.

4. fastify-mongoose

Fastify-mongoose integrates Mongoose, an ODM (Object Data Modeling) library for MongoDB, with Fastify, simplifying database interactions.

5. fastify-cors

Fastify-cors provides Cross-Origin Resource Sharing (CORS) support, allowing you to define the access policies for your Fastify server to handle requests from different origins.

Getting started with Fastify for Node.js applications

To integrate Fastify into your project, kick off by installing it:

npm install fastify

Once installed, incorporate it into your project and create a new Fastify server instance:

import Fastify from "fastify";
const fastify = Fastify();

The Fastify function allows customization through an options object. For instance, activating built-in logging and setting a timeout for incoming requests can be done like this:

const fastify = Fastify({
  logger: true,
  requestTimeout: 30000, // 30 seconds
});

With your preferred configurations in place, you're set to add your initial route:

fastify.get('/', function (request, reply) {
  reply.send("Hello world!");
});

Once you've defined your "Hello world!" route, kickstart the server by specifying your chosen localhost port:

const port = process.env.PORT || 3000;

fastify.listen({ port }, function (err, address) {
  if (err) {
    fastify.log.error(err);
    process.exit(1);
  }

  fastify.log.info(`Fastify is listening on port: ${address}`);
});

To initiate the server, run the entry file. Expect JSON log output in the console:

{"level":30,"time":1675958171939,"pid":391638,"hostname":"fedora","msg":"Server listening at http://127.0.0.1:3000"}
{"level":30,"time":1675958171940,"pid":391638,"hostname":"fedora","msg":"Server listening at http://[::1]:3000"}
{"level":30,"time":1675958171940,"pid":391638,"hostname":"fedora","msg":"Fastify is listening on port: http://127.0.0.1:3000"}

Enhance log readability in development using the pino-pretty package. After installation, pipe your program's output to the CLI:

node server.js | pino-pretty

This generates a colored output for easier readability. Enabling the logger is beneficial as it records all incoming requests in a detailed log format, providing a timestamp, request ID, response status code, and response time (in milliseconds):

The logging feature, when activated, proves invaluable by capturing every incoming server request in a detailed log format. Execute the following shell command using curl to observe the logged information:

curl "http://localhost:3000"

The resulting JSON log showcases essential details:

{
  "level": 30,
  "time": 1675961032671,
  "pid": 450514,
  "hostname": "fedora",
  "reqId": "req-1",
  "res": { "statusCode": 200 },
  "responseTime": 3.1204520016908646,
  "msg": "request completed"
}

Navigating fastify routes

Creating endpoints in Fastify is a breeze with dedicated helper methods. For HTTP GET requests, use fastify.get() as demonstrated earlier. Other methods cater to various HTTP methods:

fastify.head(path, [options], handler);
fastify.post(path, [options], handler);
fastify.put(path, [options], handler);
fastify.delete(path, [options], handler);
fastify.options(path, [options], handler);
fastify.patch(path, [options], handler);

For a universal handler across all HTTP methods for a specific route, leverage fastify.all():

fastify.all(path, [options], handler);

While the options argument is optional, it offers a spectrum of configuration settings per route. Refer to the Fastify docs for the exhaustive list of available options.

Path arguments can be static (e.g., /about or /settings/profile) or dynamic, with URL parameters accessible in the handler through request.params:

fastify.get("/:userID/repos/:projectID", function (request, reply) {
  const { userID, projectID } = request.params;
  // your code here
});

Fastify handlers follow a specific signature, with request representing the received HTTP request and reply signifying the response:

function (request, reply) {}

For asynchronous handlers, respond by returning from the function:

fastify.get("/", async function (request, reply) {
  // do some work
  return { body: true };
});

In asynchronous handlers, use await reply or return reply to prevent race conditions:

fastify.get("/", async function (request, reply) {
  // do some work
  return reply.send({ body: true });
});

Fastify routes inherently catch unhandled exceptions or promise rejections. When such instances occur, the default error handler triggers a '500 Internal Server Error' response:

fastify.get("/", function (request, reply) {
  throw new Error("Uncaught exception");
});

The corresponding JSON response using curl:

{"statusCode":500,"error":"Internal Server Error","message":"Uncaught exception"}

Tailor the default error-handling behavior using fastify.setErrorHandler(). 

Maximizing Fastify's capabilities

Let's see what else you can do with Fastify:

Validation: Fastify leverages Ajv under the hood, enabling the definition of validation rules using JSON schema. 

Logging: Fastify employs the fast and versatile logger, Pino. The logger instance is readily available on the Fastify server instance

(e.g., Fastify.log.info("...")) and on all Request objects (e.g., request.log.info("...")).

Logger usage is straightforward; however, it needs to be enabled since it is turned off by default.

You just need to do

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

Then, you can use it like:

fastify.get("/", (request, reply) => {
request.log.info("Info about request");
reply.send({ message: "hello world" });});

Error handling: Fastify facilitates error handling through the setErrorHandler() method, allowing developers to explicitly specify a function for error management. Further customization is achievable by specifying different error handlers using plugins. Fastify diligently captures various uncaught errors, whether in

synchronous routes (e.g., app.get('/', () => { throw new Error('kaboom') })) or

asynchronous routes (e.g., app.get('/', async () => { throw new Error('kaboom') })), without compromising performance.

Decorators: Fastify introduces decorators, empowering developers to tailor core Fastify objects such as the server instance, request, and reply objects used during the HTTP request lifecycle. The decorator API facilitates the attachment of various properties, including functions, plain objects, or native types, to these core objects. This capability enhances customization, allowing developers to tailor Fastify to specific project needs.

Final words

Fastify isn't just a framework; it's a robust toolkit empowering easy development of high-performance Node.js applications. Prioritizing speed and scalability, it's the ideal choice for modern, reliable APIs. 

Partner with Apptensions, where our expertise transforms ideas into transformative digital experiences. Explore possibilities; let's navigate complexities together for your project's success.

Discover More Blog Posts

Explore our collection of insightful blog posts.