Your latest Node.js content, news and updates in one place.

Choosing the right Node.js Framework: Express, Koa, or Hapi?

Node.js was first introduced 10 years ago, and in that period of time, has become the fastest-growing open source project on Earth, with +59,000 stars on GitHub and more than a billion downloads.

Part of the reason for the rapid growth in popularity was that Node.js allows developers use the same language for both the client-side and the server-side part of an application: JavaScript.

Node.js is an open-source and cross-platform JavaScript runtime environment designed for building scalable server-side network applications, and it’s a popular tool for almost any kind of project! Because of its exponential growth and popularity, many frameworks were created to enhance productivity, scalability, the speed of applications, to facilitate quick prototyping, and to automate processes with the help of libraries, templates, and reusable components.

In this article, we will explore the differences between three of the most popular frameworks in Node.js: Express, Koa, and Hapi. In a future post, we will look into Next, Nuxt and Nest.

  • The comparison is based on:

    • Popularity (GitHub Stars and npm downloads).
    • Installation.
    • Basic Hello World app.
    • Advantages.
    • Disadvantages.
    • Performance.
    • Security.
    • Community involvement.


Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications, it behaves like a middleware to help manage servers and routes.


For installing express, you need to have already installed Node.js. If you want to install express in a specific directory and save it in the dependencies list:

$ npm install express --save

However, if you want to install Express temporarily and not add it to the dependencies list, you can use:

$ npm install express --no-save

Hello World

This is the most basic example on how to create an express app that listens on port 3000 and responds “Hello World!”:

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => res.send('Hello World!'))

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

For every other path, the server will respond with 404 Not Found.


  • Almost the standard for Node.js web middleware.
  • Simple, minimalistic, flexible and scalable.
  • Fast app development.
  • Fully customizable.
  • Low learning curve.
  • Easy integration of third-party services and middleware.
  • Majorly focused on browsers, making templating and rendering an almost out of the box feature.


Although Express.js is a very convenient and easy-to-use framework, it has some minor drawbacks that may influence the development process.

  • Organization needs to be very clear to avoid problems when maintaining the code.
  • As your codebase size increases, refactoring becomes very challenging.
  • A lot of manual labor is required, since you need to create all endpoints.


Express provides a thin layer of fundamental web application features, without obscuring Node.js features that are familiar.

The best practices for improving express performance includes:

  • Use gzip compression.
  • Don’t use synchronous functions.
  • Do logging correctly (for debugging, use a special module like debug, for app activity use winston or bunyan).
  • Handle exceptions properly, using try-catch or promises.
  • Ensure your app automatically restarts by using a process manager or use an init system like systemd or upstart.
  • Run your app in a cluster. You can increase the performance of a Node.js app greatly by launching a cluster of processes (a cluster runs multiple instances of the app, distributing the load and tasks among the instances).
  • Cache request results, so that your app does not repeat the operation to serve the same request repeatedly.
  • Use a load balancer to run multiple instances of it and distribute the traffic, like Nginx or HAProxy.
  • Use a reverse proxy that performs supporting operations on the requests. It can handle error pages, compression, caching, serving files, and load balancing among other things.

A simple “Hello World” app has the following performance request per second: express performance


You can find a list of security updates in Express in the following link. Node.js vulnerabilities directly affect Express, so is important to keep an eye on Node.js vulnerabilities and make sure you are using the latest stable version of Node.js.

Community involvement

  • Number of contributors: 220
  • Closed Pull Requests: 821

The Express community meets regularly, and they communicate through their mailing list, Gitter, IRC channel, issues in GitHub, and the Express Wiki.

Finally, express is probably the most popular framework for Node.js, and there are many other popular frameworks that are built on Express.


Koa was built by the same team behind Express, and aims to be a smaller, more expressive, and more robust foundation for web applications and APIs. By leveraging async functions, Koa allows you to ditch callbacks and significantly increase error-handling. Koa does not bundle any middleware within its core, and it provides an elegant suite of methods that make writing servers fast and enjoyable.

A Koa application is an object containing an array of middleware functions which are composed and executed in a stack-like manner upon request.


Koa requires node v7.6.0 or higher for ES2015 and async function support. You need to have already installed Node.js.

You can quickly install a supported version of node.js with your favorite version manager:

$ nvm install 7
$ npm i koa
$ node my-koa-app.js

Hello World

This is the most basic example of a “Hello World!” app on Koa that listens on the port 3000.

const Koa = require('koa');
const app = new Koa();

app.use(async ctx => {
  ctx.body = 'Hello World';


For every other path, the server will respond with 404 Not Found.


  • Koa improves interoperability, robustness, and makes writing middleware much more enjoyable.
  • Has a large number of helpful methods but maintains a small footprint, as no middleware are bundled.
  • Koa is very lightweight, with just 550 lines of code.
  • Has a very good user experience.
  • Better error handling through try/catch.
  • Generated-based control flow.
  • No more callbacks, facilitating an upstream and downstream flow of control.
  • Cleaner, more readable async code.


  • The open source community around Koa is relatively small.
  • Not compatible with Express-style middleware.
  • Koa uses generators which are not compatible with any other type of Node.js framework middleware.


With Koa.js you can build web apps with great performance. This is because you can stop using callbacks, deal with errors faster, and because Koa itself is a very lightweight framework. As well as that, it makes the code management process easier.

It’s important to take into account the best practices for having a better performance in Node.js like running things in parallel, use asynchronous APIs in your code, keeping code small and light, and using gzip compression.

A simple “Hello World” app has the following performance request per second: koa performance


There are different middlewares and headers for Koa that helps to improve the security, you can find them in the following link koa security

Community involvement

  • Number of contributors: 169
  • Closed Pull Requests: 577

You can join G+ koa Community, mailing list, contribute to Koa’s repo, join koa slack or start a discussion in hashnode.


Hapi is a rich framework for building applications and services. It enables developers to focus on writing reusable application logic instead of spending time building infrastructure.

It is a configuration-driven pattern, traditionally modeled to control web server operations. A unique feature Hapi has is the ability to create a server on a specific IP, with features like the onPreHandler, we can do something with a request before it is completed by intercepting it and doing some pre-processing on the request.


To install hapi, you need to have Node.js installed and then:

npm install hapi

To save it to your package.json dependencies.

Hello World

The following example is the most basic hello world app using hapi:

'use strict';

const Hapi=require('hapi');

// Create a server with a host and port
const server=Hapi.server({

// Add the route
    handler:function(request,h) {

       return'hello world';

// Start the server
const start = async function() {

   try {
       await server.start();
   catch (err) {

   console.log('Server running at:',;


Then you just launch the application by running npm start and open localhost:8000/hello in your browser.


  • It provides a robust plugin system that allows you to add new features and fix bugs at a fast pace.
  • It enables you to build scalable APIs.
  • There is a deeper control over request handling.
  • It is an excellent choice for building Representational State Transfer (REST) APIs because it provides you with routing, input, output validation, and caching.
  • You can build an API that serves all kinds of clients that need mobile and single-page applications.
  • Detailed API reference and good support for document generation.
  • You can use hapi.js with any front-end framework, like React, Angular, and Vue.js to create a single-page application.
  • Configuration-based approach to some sub-middlewares(pseudo-middlewares)
  • Provides the availability of caching, authentication, and input validation.
  • Has a plugin-based architecture for scaling.
  • Provides really good enterprise plugins such as joi, yar, catbox, boom, tv, and travelogue.


  • Developers need to figure out the code structure on their own.
  • “Locks” developers into using hapi-specific modules and plugins such as catbox, joi, boom, tv, good, travelogue, and yar; and which are not compatible with Express/Connect.
  • Endpoints are created manually and must be tested manually.
  • Refactoring is manual.


A 2017 study on Node.js frameworks, showed that hapi performed the worst compared to the other frameworks.


As we can see in the following graph compared to express. This test is consistent with past results. Express continues to maintain a performance edge over hapi. Applications with significant performance requirements should consider the advantage Express has over Hapi.

hapi performance 2

A simple “Hello World” app has the following performance request per second: hapi performance


Different plugins can help to improve hapi security:

Crumb: Anti cross-site-request-forgery (XCSRF) token generation and validation plugin. It works both with regular requests and CORS requests (OWASP recommends using CSRF protection, such as Crumb, along with CORS). Synopsys recommends using Crumb v3.0.0 or newer since a CSRF token leakage issue has been fixed when using Crumb with CORS enabled and the request origin does not match those specified in the CORS configuration.

Joi: Object schema description language and validator for JavaScript objects. Joi allows developers to define a schema for an object and then evaluate the object against that schema thus performing input validation for the object. Everything is defined and evaluated on the server-side so that the attacker cannot easily bypass this protection.

Hapi-rbac: Allows developers to implement role-based access controls easily. Broad enough to grant or deny access to entire groups; granular enough to grant or deny access to individual users.

Blankie: Allows developers to set the Content-Security-Policy header directives easily. The CSP is flexible enough that it may be implemented on a per route basis or across all routes.

Cryptiles: Provides general purpose cryptographic utilities for random number generation, encryption, hashing and fixed-time comparisons of hashes that are based on the Node.js crypto library.

Community involvement

  • Number of contributors: 184
  • Closed Pull Requests: 1176

You can join slack channel:, visit the community page, community governance page and follow them on twitter to keep updated with the latest news.

Read More
Choosing the right Node.js Framework: Next, Nuxt, Nest?

In my previous blog post, I explored the differences, advantages, and disadvantages of three of the most popular Node.js frameworks: Express, Koa, and Hapi. In this blog post, I’m going to examine the differences between three more very popular frameworks: Next, Nuxt, and Nest. These three frameworks are server-side rendering, and they are closely related to React, Vue, and Angular (the three most widely used front-end frameworks), respectively.

  • The comparison is based on:

    • Popularity (GitHub Stars and npm downloads).
    • Installation.
    • Basic Hello World app.
    • Advantages.
    • Disadvantages.
    • Performance.
    • Community involvement.


Next is the most popular framework compared to the other two. It has more npm weekly downloads, GitHub stars and number of contributors.

Next.js is a React framework that lets you build server-side rendering and static web applications using React.


Install it:

npm install --save next react react-dom

and add a script to your package.json like this:

  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"

After that, the file-system is the main API. Every .js file becomes a route that gets automatically processed and rendered.

Basic Hello World app

Populate ./pages/index.js inside your project:

function Home() {
  return <div>Hello world!</div>;

export default Home;

Then just run npm run dev and go to http://localhost:3000. To use another port, you can run npm run dev -- -p <your port here>.


  • Every component is server-rendered by default
  • Automatic code splitting for faster page loads
  • Unnecessary code is not loaded
  • Simple client-side routing (page-based)
  • Webpack-based dev environment which supports Hot Module Replacement (HMR)
  • Fetching data is very simple
  • Can be implemented with Express or any other Node.js HTTP server
  • It’s possible to customize with your own Babel and Webpack configurations
  • Easy to deploy anywhere if Node.js is supported
  • Built-in handling of search engine optimization (SEO) for pages


  • Next.js is not backend; if you need backend logic, such as a database or an accounts server, you should keep that in a separate server application
  • Next is powerful, but If you’re creating a simple app, it can be overkill
  • All data needs to be loadable from both the client and server
  • Migrating a server-side app to Next.js is not a quick process, and depending on your project it may be too much work


To measure the performance, I used Apache Bench for benchmarking, which highlights how many requests per second the app is capable of serving. I also used lighthouse to audit performance, accessibility, best practices, and SEO.


This is a basic Hello World app in Next.js. It handles 550.87 requests per second. This value is the result of dividing the number of requests by the total time taken. The average time spent per request is 18.153 ms.

Compared to the other two frameworks, Next.js scored better overall than Nuxt.js but worse than Nest.js


In the report provided by lighthouse, we can see that the performance, accessibility, best practices, and SEO scores are all above 70, which is good, but compared with the other two frameworks, it had the lowest score for Performance and has the highest score in Best Practices.

Community involvement

The Next.js community communicates through chat, slack, issues and pull request on GitHub.

Also, in the repo awesome-nextjs, there is a list of essentials, articles, boilerplates, extensions, apps, books, and videos that are useful for developers using Next.js


Nuxt is a Vue.js Meta Framework to create complex, fast, and universal web applications quickly.


Install it:

$ npm i nuxt

To create a basic app:

$ npx create-nuxt-app <project-name>

You can start directly with the CLI create-nuxt-app for the latest updates. Or you can start by using one of the starter templates: starter: Basic Nuxt.js project template express: Nuxt.js + Express koa: Nuxt.js + Koa adonuxt: Nuxt.js + AdonisJS micro: Nuxt.js + Micro nuxtent: Nuxt.js + Nuxtent module for content heavy sites

Basic Hello World app

This is the most basic example of a “Hello World!” app on Nuxt:

    <h1>Hello world!</h1>
    <NLink to="/about">
      About Page

export default {
  head: {
    title: 'Home page'


  • Its main scope is UI rendering, while abstracting away the client/server distribution
  • Statically render your Vue apps and get all of the benefits of a universal app without a server
  • Get automatic code splitting (pre-rendered pages)
  • Setup via the command line with the starter template
  • Get great project structure by default
  • Easily set up transitions between your routes and write single file components
  • Get ES6/ES7 compilation without any extra work
  • Get set up with an auto-updating server for easy development
  • Powerful Routing System with Asynchronous Data
  • Static File Serving
  • ES6/ES7 Transpilation
  • Hot module replacement in Development
  • Pre-processor: Sass, Less, Stylus, etc.


  • It has a smaller community, which means fewer resources and potentially less extensive documentation
  • Lack of some common solid plugins/components. (Google maps, calendar, vector maps). Some components for that exist, but they are generally not very well maintained.
  • It is necessary to go deep in more complex components/plugins. If you want to develop something very flexible, you have to get down to render functions/jsx to do that. (e.g render the contents of a slot in another place/component).
  • Props have to be specified explicitly. There might be cases when you want to transform some CSS classes to props; you’ll have to specify these props or use $attrs / render functions or jsx.
  • Reactivity caveats like setting an item from an array directly this.items[key]=value or adding a new data property.
  • High traffic may put strain on your server
  • You can only query and manipulate the DOM in certain hooks



This is a basic Hello World app in Nuxt.js. It handles 190.05 requests per second. The average time spent per request is 52.619 ms. On this metric, Nuxt.js performs the worst compared to the other two frameworks.


Nuxt.js has the highest score in three of the four measures; performance, accesibility and SEO.

Community involvement

There is a GitHub organization where you can find modules and projects from the Nuxt.js community. There is also a curated list of awesome things related to Nuxt.js awesome-nuxt including Modules, tools, mention of Nuxt.js, showcase, tutorials, blogs, books, starter template, official examples, and projects using Nuxt.js.

The community communicates through Gitter Chat Room, Telegram, Russian community, Discord, Twitter and YouTube Channel


A progressive Node.js framework for building efficient, scalable, and enterprise-grade server-side applications on top of TypeScript and JavaScript (ES6, ES7, ES8), Nest is heavily inspired by Angular.

Nest is a framework for building efficient, scalable Node.js server-side applications. It uses modern JavaScript, is built with TypeScript (preserves compatibility with pure JavaScript) and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming).

Under the hood, Nest makes use of Express, but also provides compatibility with a wide range of other libraries, like e.g. Fastify, allowing for easy use of the myriad third-party plugins which are available.


Install it:

$ npm i @nestjs/cli
$ nest new project-name

Alternatively, to install the TypeScript starter project with Git:

$ git clone project
$ cd project
$ npm install
$ npm run start

Basic Hello World app

After installing Nest.js with the npm cli command, and creating a new project with nest new project-name, a src/ directory will be created and populated with several core files, including main.ts. The main.ts includes an async function, which will bootstrap our application:

import { NestFactory } from '@nestjs/core';
import { ApplicationModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(ApplicationModule);
  await app.listen(3000);

And then to run the app that listens on port 3000, you execute:

$ npm run start


  • As a TypeScript-based web framework, strict type definition is possible
  • The framework is very annotation-driven, with everything from endpoints to Swagger documentation being generated from them. The endpoints are clean and simple, and the annotations make developing simpler all around.
  • The folder structure in Nest.js is heavily based on Angular. This allows for minimal downtime when first designing a Nest service.
  • Because Nest.js is a module-based framework, it’s easyto externalize general-purpose modules and reuse code in multiple projects
  • Components get their own folders, with an application module and main file residing in the root. This simple structure allows more attention to be paid to the design of endpoints and their consumers, instead of application structure.
  • Nest.js uses the latest version of TypeScript, which helps ensure that it will remain relevant in the rapidly changing JavaScript landscape and gives developers less context switching. The transition from Angular code to Nest is relatively easy.
  • Similar to Angular, Nest also has a decent command line tool, available through Node Package Manager, nestjs/cli. The command line tool will let you scaffold the project, generate Nest architecture components, and display project information.


  • The largest risk facing Nest users is the lack of documentation. The framework has great integrations with other frameworks but the documentation is minimal and doesn’t cover any issues that may arise.
  • Nest does hold an edge in its use of TypeScript and relation to Angular, but it doesn’t have the backing power of a large enterprise behind it.
  • Overall, Nest has a smaller community compared to other frameworks



This is a basic Hello World app in Nest.js. It handles 928.18 requests per second. The average time spent per request is 10.774 ms. On this metric, Nest.js performed the best out of the three frameworks we compared.


In the report provided by lighthouse, Nest.js has a very high performance, but scored comparatively lower on other key factors:accessibility, best practices and SEO.

Community involvement

There is a group of developers providing handy packages on NestJS Community organization GitHub. Some of their popular packages are: nestjs-config, a config module for NestJS using dotenv. nest-access-control, Role and Attribute-based access control for NestJS and nestjs-flub, pretty error stack viewer.

Even if Nest is not the most popular framework, is the one that has the better performance and has many advantages. You should give it a try!

The community has a spectrum chat and Twitter

Read More