Building ultra-fast REST APIs with Node.js (restana vs express vs fastify)

Introduction

restana is a blazing fast and minimalist connect-like+ middleware compatible framework optimised for performant REST APIs. Currently the faster “usable” Node.js framework listed in:

https://github.com/the-benchmarker/web-frameworks

restana framework analogy ;) — photo courtesy of https://pexels.com

Not just another framework

Short time ago, when I was contributing to the Hydra Integration project, I had the opportunity to face closer how big is the overhead of the existing Top 10 Node.js Frameworks for building minimalist REST APIs.

In modern architectures, where micro-services become the ultimate “stupid computing instance”, using Express or Hapi.js should be seen as an unnecessary technological decision. That’s one of the reasons of the increasing popularity of serverless-like alternatives.

So let’s draw what I wanted to have in a framework back in the time:

  • Low overhead, zero friction HTTP Server abstraction (HTTPS, HTTP2 compatible).
  • Request (method + path) routing capabilities.
  • Connect-like middleware compatible (so we can re-use hundreds of existing middlewares).
  • Async/Await compatible.
  • Content-Type = application/json as first class citizen.
  • Low memory consumption, high throughput.
  • Swagger compatible.

…and that was how restana was born!

https://www.npmjs.com/package/restana

const service = require('restana')({})

service.get('/hi', (req, res) => {
  res.send('Hello World!')
})
service.start()

Reaching the performance limits (native vs express vs fastify vs restana)

Node.js native service: GET http://localhost:3000/hi

const http = require('http')

const service = new http.Server()
service.on('request', (req, res) => {
  if (req.method === 'GET' && req.url === '/hi') {
    res.writeHead(200, { 'Content-Type': 'text/plain' })
    res.end('Hello World!')
  } else {
    res.statusCode = 404
    res.end()
  }
})

service.listen(3000)

Express service equivalent: GET http://localhost:3000/hi

const service = require('express')({})

service.get('/hi', (req, res) => {
  res.send('Hello World!')
})
service.listen(3000)

Fastify service equivalent: GET http://localhost:3000/hi

const fastify = require('fastify')()

fastify.get('/hi', async (request, reply) => {
  return 'Hello World!'
})
fastify.listen(3000)

Restana service equivalent: GET http://localhost:3000/hi

const service = require('restana')({})

service.get('/hi', (req, res) => {
  res.send('Hello World!')
})
service.start(3000)

wrk -t8 -c8 -d30s http://localhost:3000/hi
(Node v10.16.0 — MacBook Pro 2016, 2,7 GHz Intel Core i7, 16 GB 2133 MHz LPDDR3)

Express: 19478.33 reqs/sec
Native: 39548.49 reqs/sec
Fastify: 45343.49 reqs/sec
Restana: 60300.62 reqs/sec

Restana + Cluster Mode: 84804.81 reqs/sec

Next generation, faster connect-like middlewares (+)

service.use((req, res, next) => {
  const now = new Date().getTime()

  res.on('response', (e) => {
    e.res.setHeader('x-response-time', new Date().getTime() - now)
  })

  return next()
})

Conclusions

restana is the #1 Node.js framework listed in “The Web Frameworks Benchmark Index” https://github.com/the-benchmarker/web-frameworks and an optimal alternative for micro-services and backend APIs.

Are you ready?

https://www.npmjs.com/package/restana

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.