Fastify.js - back to the future?
Fastify.js introduces itself as:
a Fast and low-overhead web-framework for Node.js.
Comm`on. Given such a premise, who wouln’d want that?
However, before I dive in - I have to give this:
Disclaimer. I have came accross Fastify in it’s early days, and found it imature. Now it has come to my desk again and I’m very pleased with what I see. However, despite the warm recommendations I give here - the customers I’m working with have chosen to proceed without it, so I can’t say I have experience with it much over the tests and evaluations I do in my sandbox, althemore in production. Having that said, there are some sizable companies that do use it, as observed on their home-page.
Now, having that out of the way - let me share you with everyting I got.
NodeJS as evolved a lot since the days it was born, and web frameworks are expected to keep up the pace. Fastify is a modern web-framework built to leverage NodeJS new features and the knowhow accumulated in the community. Doing that it gets to be very efficient and a well-designed framework that tries to bring us back to the future, shaking design decisions that have become less relevant due the changes the JS language spec and implementation have adopted lately. However, because of this attempt to shake these patterns - the migration to it is not smooth: it comes with a risk and a cost. Based on the premise and the sandbox experiments I did - my opinion is that it worths it. But yet, not everybody can hop on. Here’s Why.
So, what’s Fastify.js?
Putting it even shorter based on their own intro:
- highly performant - with some nice bencharks to proove it
- Extendible - i.e built with requirements of a plugin architecture
- Schema based - leveraging swagger and JSON-Schema to perform validations for you
- Logging - ships with pino - a superhero on it’s own right
- Developer Friendly - expressive api
- TypeScript ready - has mature TypeScript declarations for you.
So what’s in Fastify.js for me?
Refining these declaration puts you in two main benefits.
- Performance boost
- Better programming expereince
From the myriad of choices in our exploded npm echosystem, every component that made it into fastify is closely monitored and carefully selected with performance and programming experience in mind. Looking inside Fastify was like a tour in an idealist muselium. Sure, it’s an evolving work in progress - but wheverywhere you look you identify design goals and design decisions.
So to their own summary I can add:
- Ownership and involvement from top notches.
Lets break that down
Every mechanism and algorithm is considered for performance first. Every choice made is for slim overhead and sleek performance. Going through the discourses in the github issues - you see how the conversation is kept performance aware.
From what I found:
- uses middie for mw-chain management
- uses a bitrix-tree to handle routing matches
- uses super-lean and efficient body parsing (extensible)
- uses optimized JSON serializer for response rendering using fast-json-strinfify
- comes with pino longer built-in - which is by right a performance-hero on it’s own
- built-in support for HTTP2
- full async-support - routers can accept async functions/methods. But not only routes. e.g. - Factories as well.
- well documented lifecycle (which is a little sophisticated, but optimized for performance, and allows the next point:)
- out-of-the-box http-error handling (customizable)
- out-of-the-box correlation-id tracking
- out-of-the-box per-route JSON-schema validations using ajv
- does not “pollute” core objects - API enhancements are provided via aggregation, and references to the core objects are preserved.
- semi-opinionated - you can do what you like, but docs come with the good patterns and the discourse is kept concern-aware
- smart plugin-architecture based on avvio (however, it’s extended internally)
- ecosystem nourishment result in an ecosystem that is mature and relatively refined
- For whoever likes it - they sacredly keep their TS defs up to date.
The lead characters are Tomas Della Vedova, and Mateo Collina, both are quality people, the latter is a nodejs core member associated with a lot of work on streaming APIs. We actually got to see him in the last NodeTLV (from Italy.. - in remote because of CoViD19).
As such they inspire a very involved and caring culture, and put a minimum bar for what they would officially include as part of the ecosystem they norish for Fastify.js.
So, lets just migrate?
Eh. Not so fast. ATM - since it introduces some new concepts, it is not fully compatible with existing frameworks. However, I do warmly recommend it for new projects.
But if you do consider to migrate - here’s the code changes you’re considering to commit to.
- logger - winston is the old world. all hail pino. But sadly, I still see winston wherever I go. Mind that winston accept an optional meta as the last parameter, and pino expects his meta first. You can create your wrapper to find your meta-object and move it to the first argument - but it will never be bullet-proof, but some best-effort code at best.
- mw - most express middleware will work with fastify, not all.
- due the bitrix-tree router - express routers will not work. It has it’s own way to handle routing - which I personally find superior by far - that’s what features the JSON-schema validations and the built-in error-handling.
- cleanup - many of the validation and the view work is done for you - so that’s codes you’ll have to rephrase and cleanup.
- toolbox - have a look at fastify-sensible - is a pack of rather small (but not part of the bare-minimum) plugins that make programming endpoints a breeze, and help you separate logic from views.
- ioc & di - if you’re used to having your modules and services require directly each other and relay on
require.cacheto be the IOC bag of already initiated modules, instead of destructuring shared dependencies from an IOC bag - you’ll have to retouch them here as well. BTW - You only have to do that for shared dependencies. Modules still can require and instantiate inner modules they fully own.
If that does not dismay you - you have my respect. Fire at will!!
If it does look a bit intimidating - the next part is for you.
What have we got so far, without Fastify
What have we got so far? What’s wrong with what we’ve got? What’s our present standard?
Callback-based middlewares, with node core objects such as request and response augmented (or decorated. however you call it) with api improvements and usability methods. Everything around this is a philosophical debate if to pass a context with references and
(req, res, next). Restify brings focus on
rest, Happi puts effort on looking sleek and make you happy, and I can go on. But none of them aim at improving this same wheel of callback based middlewares with nodejs core objects. They all wanted to enjoy from the existing echosystem and inherited the limits that come with it’s spec.
So - all the frameworks that keep this “golden” standard - had to commit to backward compatibility of a spec that has evolved in a world that predated promises as part of Node, and that the steaming APIs was much less mature than it is today, Therefore they are bound to carry the design decisions were taken back then:
- callback-based middlewares
- fully modular - logger independent, debug with
- modularity based mostly on middlewares
- the middleware contract - emit a response OR call next, and frameworks that require both need adaptations and hence feel a bit odd (that’s what prevents a centralized error-hanlding).
- the user can express less-than-ideal flows - like putting
This, together with the explosion of the npm echosystem, puts on the edge-developer a lot of choices, many of them come with a hidden cost, and sadly - including many which are still the package of choice. (gosh - some of the libs in use today even predated XSS standards. Remember those days?).
No, no no. We’re in a stage where when we want to move forward we have to let things go, and that’s what’s Fastify is trying to provide.
It’s not just web-frameworks. If we dont adapt and progress, NodeJS will be replaced the same way it had replaced other frameworks before. Heard of deno?
To Sum Up…
Fastify is out there for a while, it feels stable and it’s used in production.
v2.x was released last year, and is stable. I’ts time to hop on.
It’s yummy: lightweight, well designed, well norished, and it’s performant.
Howeve4r, it’s ecosystem is still growing and does not provide solutions for everything (e.g. passport). That is sure to change the more people hop on.
Get started with your back-end services, and see for yourself how it makes it’s way to your front.
We will contact you as soon as possible.