Editor’s note: This article was last updated on 15 December 2022 to include information about Express v5.0, which is in beta at the time of writing.
With Node.js, you can create production-ready applications, including real-time chat applications, microservices, command line tools, web servers, and APIs. Thanks to its event-driven model, Node.js can handle a large number of concurrent requests. Many large companies use Node.js in production, including Netflix, Uber, Nasa, PayPal, and Walmart, to name a few.
In this article, we’ll compare a few popular Node.js frameworks according to their usage, features, disadvantages, downloads, and more. Let’s get started!
Writing server-side logic is complex, and coding an entire app from scratch is time consuming. Developers need to focus on the business logic rather than wasting time creating an app from scratch. By providing helper functions, tools, and rules, frameworks handle the heavy lifting, helping us to structure our application and write clean code quickly.
Many web frameworks abstract web protocols into higher-level APIs and provide a rich interface for building web applications. Typically, these frameworks use the underlying, built-in power of Node.js and provide us with a simpler API to create more complicated features in our web servers. Of course, frameworks add abstraction to our code, but if you’re building a large web application, they can come in handy.
Every framework tries to solve a problem, and the philosophies of each framework will differ. However, all Node.js frameworks share some commonalities, like mapping URLs to content, known as routing, and templating for dynamic content.
Although you might feel excited to learn a new framework, the sheer number of frameworks available may overwhelm you. The diagram below can help you understand which framework might be the best choice for your unique project:
There are many different ways to group frameworks, and some frameworks can belong to multiple categories. For example, I’ve included NestJS under REST API, but you can also use it as a full-stack and MVC framework. Or, you can just spin up a REST API server.
HTTP server frameworks are based on Express, helping you build apps based around HTTP verbs and routes. Several popular HTTP server frameworks include Fastify, a low overhead framework for backend development, Koa, which was designed by the Express team, and Hapi, an alternative to NestJS.
MVC stands for Model, View, and Controller, a software architecture design pattern that splits application functionality into three parts:
Models handle data logic and represent how data is stored. Views handle presenting the information to the user, and controllers handle request flows and delegating information between the model and the view. The controller will get the data information from the model and then pass that data into the view.
Sails, Strapi, and AdonisJS support MVC architecture; if you don’t want to spend time structuring your apps, you can use these. In addition, having MVC architecture makes it easy for other developers to understand your code.
NestJS, Loopback, and Restify are REST API frameworks. You can use these frameworks to spin up a fast Node.js server or just to handle CRUD requests.
The diagram below will give you an idea of how popular the framework is at the time of writing, including how many contributors it has, monthly downloads on npm, and the age of the framework:
Most of these frameworks are pretty old, and the leading framework with the most downloads on npm is Express. Following Express, we have Koa, then Fastify. As for their popularity on GitHub, Express and Socket.io are leaders, with Meteor, NestJS, and Strapi following behind.
We’ll review five of the most popular frameworks, Express, Koa, Socket.io, NestJS, and Fastify, exploring their features, selling points, and which companies are using them.
Express is inspired by the Sinatra framework because of Ruby’s efficiency and maintainability. Designed to build and run web apps quickly, developers love Express because it is lightweight, fast, minimalistic, and unopinionated.
Express offers features like routing and middleware that speed up the process by requiring only a few lines of code. Express is only a thin layer to Node.js, and because of Node’s asynchronous nature, we can run multiple requests concurrently. Therefore, Express provides high performance and a fast development experience.
Express doesn’t provide a universal way to organize things. There are no strict rules, so you can decide how to structure your app or what middleware to use. For example, you are free to choose any design pattern, like MVC, MVP, MVVM, etc. However, the most common is the MVC pattern.
With Express, it’s easy to integrate third-party services and middleware for tasks like parsing requests, cookie headers, sessions, security headers, or libraries. This allows you to use additional libraries for authentication, database access, session management, and much more. You can easily integrate with SQL or NoSQL databases.
On the other hand, Express requires a lot of labor intensive tasks, like setting up endpoints and middleware. Since Express is unopinionated, you need to configure libraries and features yourself.
While writing Express code, you might run into callback hell or pyramid of doom. You can solve this problem by using Promises. Due to the architecture of Express, managing large-scale projects by a team of developers can be difficult.
Express is used by companies like Mulesoft, IBM, Yandex, Uber, and Accenture. Express is flexible, and you can build any kind of single-page, multi-page, or hybrid web and mobile application of any size. You can start by building simple static file servers to JSON APIs.
If we compare Koa and Express, we can see that Koa has removed most of the features found in Express. Koa is very unopinionated, and it doesn’t ship routing, the templating engine, or JSONP out of the box. The main reasoning behind this is to make Koa faster, giving developers more freedom and posing fewer complexities while writing code.
Koa also has more options for customization. So, if a developer wants to work with middleware, they can create it themselves or use the built-in middleware. Koa provides add-on modules like Koa router, Koa EJS templating, Koa Body Parser, and much more.
yield keyword to exit and then reenter.
Koa uses a
context object, which encapsulates
req/res objects into one, helping developers build APIs more efficiently by using several helpful methods. Finally, Koa uses cascading middleware. Thanks to asynchronous functions, middleware will run in a cascading fashion until the last middleware is reached.
If you know Express, Koa is easy to learn, and with only 600 lines of code, it helps developers write thinner middleware. In comparison to Express, Koa is more performant for handling more requests per second, has better control over error handling with
try...catch, and is more modular. Due to its modularization, refactoring larger code bases in Koa is easy, and it provides a minimal interface for developing apps and APIs.
Koa is not compatible with Express-style middleware, and it uses ES6 generators, which are not compatible with middleware from other frameworks. Generators make it harder to migrate to other Node.js frameworks in the future, and it creates tight coupling with the framework. Finally, Koa doesn’t have a built-in middleware, and conventional middleware like
next don’t work with Koa.
Paralect, GAPO, and the Shimo website all use Koa. Koa is great for building scalable, lightweight web apps, HTTP APIs, and single page web apps.
Socket.io is mainly used for building real time chat applications like WhatsApp and Facebook Messenger. It establishes bidirectional communication between the web client and servers:
To better understand this, we need to understand how clients and servers normally communicate over HTTP. The client makes a request, and the server responds to the client’s request. But, this is a one-way communication; the server cannot start communication with the client because the HTTP protocol is stateless, and it is hard for the server to find the IP addresses of all the different clients that are accessing it.
In some situations, the server needs to update the client in real time. For example, if we have a chat application, the server should broadcast new messages instantly to all users. Instead of using an HTTP connection, we need to use WebSockets, which allows real time, two-way communication between the frontend and backend.
Socket.io has two parts, a client-side library that runs on the browser and a server-side package for Node.js. Both components have an API that is nearly identical because we can run code both in the browser and server. It follows the
EventEmitter model of Node.js. For WebSockets to work, the client opens a persistent connection to the server, and both parties can send messages back and forth to each other.
Socket.io provides a reliable WebSocket connection for Node.js applications. It provides real time analytics in fewer lines of code with high speed support.
If the server and client don’t agree on a handshake, Socket.io falls back to long polling and supports alternative protocols, like WebSockets, Flash, XHR, and JSONP. It can support a wide range of browsers.
Socket.io also features binary and multiplexing support. We can send any blob data, like images, audio, or video from the client or server side.
Additionally, the Socket.io framework offers auto reconnection support. If a client is disconnected, it will keep retrying unless stopped manually. Finally, Socket.io features automatic error detection and correction, and it forges deep connections even in the presence of proxies and private firewalls.
Socket.io has built in support for adding middleware and provides a more straightforward way of setting up audio and video streaming functionalities. It’s easy to get started, and you can develop applications quickly. Finally, Socket.io has a large community, so it’s pretty easy to find learning resources.
Socket.io uses callbacks, and it doesn’t provide any message guarantee to acknowledge that it received a message. Therefore, we need to write custom logic in our application to handle such scenarios.
Websites and apps like Patreon, Alibaba Travels, Plaid, Trello, Bepro, and Barogo all use Socket.io. Socket.io is useful for video conferencing apps, interactive streaming media, multiplayer games, and dynamically updated social network sites.
Inspired by Hapi and Express, Fastify claims to be the fastest web framework around, and, according to its benchmarks, it’s twice as fast as Express. The only case where Fastify falls behind Express is in handling empty requests. Fastify focuses on minimizing performance overhead with a powerful plugin architecture, all while keeping the developer experience in mind.
According to the 2021 State of JS Survey, Express is the most used backend framework at 81 percent, followed by Next.js at 45 percent. Fastify comes in later at 11 percent.
Fastify automatically parses JSON with efficient rendering and provides quick routing. Therefore, it is highly performant, and it can serve up to 30,000 requests per second.
Thanks to its ecosystem of 200 plugins, hooks, and decorators, Fastify is extensible. Fastify also works well with TypeScript, supports AWS Lambda, has a GraphQL adapter, and comes with a lightweight logger.
Finally, Fastify shuts down an application gracefully. It stops accepting new connections and works to close all outstanding “keep alive” connections before exiting the process.
Fastify offers zero overhead in production, automatic security and data validation, long-term support for semantic versioning, and a cleaner syntax for writing async code in controllers. With Fastify, testing is easy, leading to a great developer experience.
Fastify doesn’t have a huge community. Therefore, if you’re stuck with a bug, you may need to fix it yourself. Additionally, Fastify has a shared ownership principle, meaning you can create a PR and contribute to the community.
Microsoft, Hotstar, and Future Foundry all use Fastify.
While you can use Fastify to create web applications, it excels when you’re building JSON-based APIs. Fastify works great for small and big projects alike; it scales well. You can easily migrate to microservices, or even serverless, and back.
NestJS is a progressive, flexible, and versatile REST API framework known for building efficient, reliable, and scalable server-side applications.
NestJS builds upon Express internally, but you can also configure it with Fastify. NestJS is inspired by Angular; it uses the concepts of dependency injection, modularity, and decorators. You can build MVC apps, REST, and GraphQL APIs. NestJS provides a built in wrapper around Apollo GraphQL.
NestJS provides a powerful CLI to boost productivity and ease the development process. It also supports REST and GraphQL APIs out of the box, and you might use it to build a full-stack application.
NestJS provides an option to build microservice-based applications out of the box. When you spin up a NestJS server, it comes with a clear architecture based on a few simple components, like controllers, modules, and providers. This makes it easy to split applications into microservices.
Finally, NestJS offers easy unit-testing for applications, including dedicated setups for all kinds of application testing.
NestJS code generation helps to develop applications faster, and it follows strict design principles that do a lot of basic development activities for developers. NestJS’s community is quickly growing.
NestJS uses Angular concepts, so for developers who aren’t familiar with Angular, it may be hard to grasp NestJS at first. When compared with Express, the NestJS community is small.
Adidas, Autodesk, Neoteric, and Sanofi all use NestJS.
NestJS is great for building complex, large-scale enterprise applications.
In this article, we’ve covered quite a lot, starting off with why you should use a framework, types of frameworks, and some statistics regarding different frameworks. We then went over the five most popular frameworks, including Express, Koa, Socket.io, Fastify, and NestJS. Hopefully, this article gave you a better idea of how each frameworks differs. As always, the right choice will depend on your unique project. What do you think of these frameworks? Did I miss your favorite? Let me know in the comments below.
Deploying a Node-based web app or website is the easy part. Making sure your Node instance continues to serve resources to your app is where things get tougher. If you’re interested in ensuring requests to the backend or third-party services are successful, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens while a user interacts with your app. Instead of guessing why problems happen, you can aggregate and report on problematic network requests to quickly understand the root cause.
LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. Start monitoring for free.
Implementing OTA in-app updates in React Native apps can streamline the update process, preventing delays that hinder overall productivity.
StyleX is a build-time, type-safe CSS-in-JS library recently open sourced by Meta. Explore StyleX and the evolution of styling libraries.
Learn to set up a completely custom Astro ecommerce implementation that’s also highly performant and type-safe in this straightforward guide.
Let’s build a Next.js app that implements vector search using Supabase and OpenAI to offer better search experiences for users.