Ep.09: Fastify (Basic App for Node Backend Frameworks Comparison)
Teolin Codreanu
Software Developer | Microservices / APIs in Node.js, JavaScript, TypeScript, Nest.js / Koa / Express etc
This article is part of an in-depth comparison series of the top Node frameworks. We'll cover all the important aspects: market share, learning curve
Table of contents
You've probably noticed that some of the frameworks we're comparing are radically different, like Nest.js. We've seen that Nest is built on top of Express or Fastify. This brings us to Fastify, an apparently simpler framework - with a twist. Well, several twists. In fact, quite a few, almost like a rock'n'roll tune. In the big 5 Whales Pool, Fastify plays the role of the fin-whale, slim and fast.
According to itself, Fastify is a "web framework highly focused on providing the best developer experience
Well, it tries to make your life easier by providing support for async/await operations and dependency injection
Their namesake claim is speed. Well, ahem... in the Node world, anything that claims it's blazing-fast, it's probably not. If you have a need for speed, you're barking at the wrong tree here, you should go for something closer to the metal like C++, Go or Rust. Node.js excels in building scalable and efficient network applications and offers an amazingly vast ecosystem of ready-made solutions that can make development easier and faster but does not shine when it comes to speed or computing prowess.
That being said, many benchmarks do place Fastify ahead of Koa, Express or even vanilla Node. Most of these benchmarks are synthetic, and I'm not completely sure they reflect real-life usage, so we're going to use the apps we're currently building to put that claim to the test later on.
If you're curious about what makes Fastify faster, it claims it's due to its superior serialisation through the use of schemas for routing. The standard JSON parser could indeed be slowing other frameworks, although I noticed others picked up on this and use alternatives (for example, if you look under the hood of Nest, you'll see it uses an alternative to JSON.stringify that is 4 to 6 times faster). Other sources of speed are async/await support, dependency injection, HTTP2 and 3 support, and radix-based routing.
Analysis (Fastify v4.27.0)
So, what are the stats? Let's dive in.
Schema-based routing
Fastify comes bundled with its own CLI, which you can install globally. I've tried to jumpstart our project with it, but it's not very useful, as it generates a few hello-world apps which are not what we need. So I started from scratch.
The second thing that I learned is that there are two ways to do routing, Express-style (no schema) and the Fastify-style (yup, schema):
Having a schema comes with benefits: type-safety
领英推荐
Basic Todo App
Transpiling the single-file-in-memory-storage-fully-synchronous version was a very straightforward affair, and it looks pretty much like Express:
There are a few differences you'll notice:
// Express:
res.status(500).json({ message: error.message })
// Fastify:
res.code(500).send({ message: error.message })
Everything else is the same.
Modular app variant
I had a harder time setting up the modular version of our app, as Fastify does not actually have a router. There are multiple solutions to this, I went with the one suggested by the documentation: using app.register() to register a specific set of routes.
The tricky bit was exporting them. Previously I just exported a router object, but Fastify wasn't thrilled with that and kept complaining it needs a function. So, I did what I had to do and came up with this ugly bastard:
That probably shows I have zero experience with Fastify, I bet there's a better way to do that. If you happen to be best buddies with the framework, have a look at the repo and suggest a better solution - I'd be happy to improve on that.
So, that being said, we now have two versions of our app, a single file and a modular version, both using in-memory storage, both completely synchronous, so this should allow us to benchmark the core performance of the framework, without any milliseconds lost to I/O.