
JavaScript has grown far beyond the browser. It now powers millions of backend systems, APIs, and cloud services through Node.js, which is one of the most widely deployed runtimes on the planet. Keeping such a critical piece of infrastructure fast,
Loading summary
Josh Goldberg
JavaScript has grown far beyond the browser. It now powers millions of backend systems, APIs and cloud services through Node JS, which is one of the most widely deployed runtimes on the planet. Keeping such a critical piece of infrastructure fast, secure and stable is a massive engineering challenge, and the work behind it is often invisible. Rafael Gonzaga is a principal open Source Engineer at NodeSource and a member of the Node JS Technical Steering Committee. He spent years digging into the performance and security layers of Nodes Core, helping shape the direction of the runtime itself. Rafael joins the show to talk about the state of Node JS performance, how benchmarking really works, the balance between speed and stability, and what it means to contribute to one of the world's most important open source projects. This episode is hosted by Josh Goldberg, an independent full time open source developer. Josh works on projects in the TypeScript ecosystem ecosystem, most notably TypeScript ESLint, a powerful static analysis toolset for JavaScript and TypeScript. He is also the author of the O'Reilly Learning TypeScript book, a Microsoft MVP for Developer technologies, and a co founder of SquiggleConf, a conference for excellent web developer tooling. Find Josh on bluesky, Fostodon and dot com as Joshua K. Goldberg.
With me today is Rafael Gonzaga, principal open Source Engineer at NodeSource. Welcome to Software Engineering Daily.
Rafael Gonzaga
Hello. Thank you. I'm happy to be here.
Josh Goldberg
We're excited to have you. You do a lot of great stuff with Node JS and performance and userland libraries. But before we get into all that, how did you get into coding?
Rafael Gonzaga
Well, it started since I was a teenager. I always been in computers since I was young. I played a lot of games but my father is blind and back in the time he couldn't make a few things on computer because of the disability. And then I started creating a visual or kind of talkback. I tried to do that at least and then my journey in the computer science started. I tried to make it happened with Python Python 2 back in the time, I don't remember, I couldn't make it work. But then I learned okay, this is how I could make a calculator, this is how I could make things to work. So I started there, but till now I couldn't make it. But there are plenty of good apps nowadays that he uses and I'm still helping with some plugins and things like that.
Josh Goldberg
So do you have experience then with accessibility technology and writing things for folks who are for example, blind?
Rafael Gonzaga
To be honest, my focus is on backend, so accessibility on web browsers is not my thing, but I know exactly the problem that it causes because very often my father calls me, okay, Facebook is not working anymore, they changed something. Can you help me? And then I need to write a chrome extension that will replace the element to the old way that he's used to get and make that happen. But on front end I'm not that person.
Josh Goldberg
But you do work in an area that sometimes folks erroneously called front end. So I think we should take a moment here to recognize that JavaScript is not a purely front end technology. It's very possible to spend much of your career in say Node JS and JavaScript and being entirely back end, what do you think of the areas that your code has touched or the stuff that people use your areas for?
Rafael Gonzaga
Well, I always loved low level programming, so I started with Python but then I suddenly jumped to C and C I learned most of the things outside of university, by the way, I haven't completed my degree, so I don't have degree nowadays. And then during the process I learned many, many languages. I came from Elixir, Erlang, I went to PHP C, but I still learned Ahab Studio working on personal projects with C and C. Then I found that, okay, there's JavaScript, people use JavaScript on front end but I don't like frontend too much. Then I saw okay, people were running JavaScript in backend. I tried, okay, let's see how it works. And my first attempt with Node JS was in a hackathon a long, long time ago. And then I could make an HTTP server and then I saw, okay, that's nice, let me see how it was created. And then I saw the GitHub repository and then okay, they use C so I could help in that part. Then I started looking to it, but I didn't make the contribution back in the time.
Josh Goldberg
But yeah, so how did you go from starting to look at Node to becoming a member of the Node Technical Steering committee?
Rafael Gonzaga
Okay, I have started on FastFi, an HTTP framework when I was working as a soft engineer in a company that was about to switch other PHP projects to Node J. They were looking to a microservice approach and then I was responsible to make that migration. So I was investigating, okay, we are about to use Node js but let me make some tests to see how well scale this new platform. Then I saw some HTTP frameworks like Express and a lot of people were advocating about Express and all the resources you find in the Internet they use Express but I made some benchmarks and Express was not fast as I thought it could be. And then I was looking, okay, let me see if there are other ATP frameworks because Express is not official from the Node JS team, right? It's a library as well as fastfi. And then I tried Fastify and I saw the benchmarks page from then and I saw, okay, this is nice. The results is exactly what I was expecting. But I found a bug during the process and I decided, okay, let me create that request. That shouldn't be a difficult. I wrote the request, it was accepted, and then I saw, okay, the community was very welcome and I decided to keep contributing to Fastify. Then I met Matteo, Matteo Collina, one of the Fastify creators during the process that told me, do you want to apply to a position at Nearform? I said, yes, I made the test, which is very curious because something got wrong in the process. And then I did the test for a senior front end engineer and I passed, but I haven't worked as a front end engineer at all, but I passed anyway. Then after passing, I got migrated to Matteo's dean and then I got some tickets to work on Node JS Core. And one of my first pull requests, Node JS was fixing a memory leak on a Windows 2012 server, 32 bits. And I spent, I don't know, two weeks or three weeks working on that. And it was very hard because I had to SSH into a machine which was far away from me. And I was testing the bug in memory lakes and I could fix that bug. After that, I learned a lot about Node JS Core and then I started doing a lot of stuff and I got nominated to Node JS Core. And then almost three years ago, I got nominated to Node jsdsc.
Josh Goldberg
What does it mean for someone to be on the TSC for Node?
Rafael Gonzaga
It's very important to be part or to have a voice in technical discussions. But to be honest, if you are a Node JS collaborator or if you are outside of Node JS team, you can still advocate you can you share your opinion. It's more about being more proactive on helping new members or discussing new features and having more context about Node JS in general. So if someone attempts to include, okay, let's reshape Node js, so let's remove C and move that to Rust. Normally the TST team are the set of people that will say if that's possible or not. And also in case of discussions, they have a vote if we should do it or not. So it's important, but it shouldn't be something that should guide people to get that role. To be honest, it's more about having a voice. I think voice is not the correct term here because technically the TSC was created just to guide the project, but we shouldn't have more power than any other contributor. That's what I'm trying to say. A TSC member shouldn't be anything different from a Node JS core collaborator. Anything that a core collaborator does, a TSC can do, and vice versa. So I don't know if I could explain that well. But yeah, that's the idea.
Josh Goldberg
It's kind of amorphous being a Technical Steering committee member on a project that doesn't have one single tracking company or one single charter. But your area has typically been performance, and you've written quite a lot about node performance. How do you see that evolving these days?
Rafael Gonzaga
Currently I work on Node JS security and performance performance. I normally do it because all my studies, my research are in performance. However, I've been paid to work full time on Node Js to focus on security, so I have these two fields for performance. I have been monitoring Node JS performance for quite a while. I have a lot of projects around that, and recently I'm leading the performance initiative of Node js. However, due to a restrict bandwidth, I don't have much time to work on that because I'm not paid full time on performance. But in security I normally write some reports like the state of Node JS performance and the Node JS have been evolving a lot of mostly due to V8 improvements. So V8 is doing a very good job in JavaScript. So some performance improvement came from V8 per se, and some of them is because Node JS is migrating most of its API from JavaScript to C. In the past we had a lot of discussions if we should write APIs in C or JavaScript, and the reason that some of them were writing in JavaScript is because it's way easier to get contributors for JavaScript than C. So okay, some API, let's write it in JavaScript because it's easy to get maintenance. But then we saw okay, for these specific APIs, JavaScript will be a bottleneck. So let's move that to the C part of Node js. Then we moved and then we saw okay, we got a significant performance improvement. And if you compare the Node JS startup, for instance, we got a significant improvement. And that applies to lambda providers. If you are using lambda on AWS or Vercel, even Cloudflare workers, you see that it's very important for them to have a very fast cold start. But I would say that those new runtimes like Ban and Deno, they have moved Node JS to get a different point of view in terms of performance. We were more stable in the past, not releasing many features and being more assertive, but now we have switched a bit our focus to hear more about the community. If community wants some modules like Escalite, let's do that. It doesn't need to be so satisfying for maintainers. So we have that and we have a more strict focus on performance. So we are actively monitoring benchmarks, micro benchmarks of Node js. And to be honest, it's very hard to Write benchmarks in JavaScript in general because of V8. V8 can be very tricky. It's most of the time smarter than you and if you are writing a micro benchmark, it's possibly you are looking to the wrong metric. So it's very hard to make some comparisons because some API might be fast on your machine or in your workload, and with a different workload or running that for more time it will cause more de optimizations. Optimizations or garbage collectors and then you see a different performance. But yeah, I would say that Node JS is way faster than two years ago.
Josh Goldberg
I want to walk through a couple of scenarios with you just to help flesh out what you're saying. Do you recall a performance optimization you attempted, a node that did not work out after running all those optimizations and benchmarks?
Rafael Gonzaga
Yes, there are plenty of them, to be honest. At Node there's a working group called Node JS performance which stores most of the issues that people find about regressions in Node JS in general. Some of them we were investigating, I believe it was from Node JS18 to Node JS20 or on a specific version of Node JS20, which MATLAB compiler inside v8 was introduced and enabled by default. After that we have received some issues saying, okay, my micro benchmark is telling me that my code is 50% is lower than in a previous version of Node JS. Then we came up to investigate and the reason is that Maglev was if you run that piece of micro benchmark for a short period of time, Maglev was being introduced and this was causing some slow operations. But turns out that if you run that with a production workload and running with a reasonable amount of time, Maglev was being called, but then it was moved to the turbofan, which is the optimized bytecode of V8 and then the result or the performance of the code was similar. So for short scripts that might be a performance bottleneck, but long life HTTP servers the performance was the same. So it's very tricky to measure micro benchmarks in JavaScript because you might be measuring a no operation because v8 optimizer code away you might be measuring a non production or an unrealistic workload because you will never run that function many times as you are measuring and some of them for instance in a specific version of V8 if you are converting a string to an integer using parseint in comparison to a plus sign O, the plus sign O was, I don't know, 10 times faster than parseint in some V8 versions. I have shared that on Twitter. I have a repository that monitors all those micro operations and I also wrote about that and it was fixed by V8 and turns out that most of the cases if you attempt to switch all parsing to plus sign O it will only give you 0.0005 milliseconds of performance improvement. So most of the time it doesn't worth the change. So it's tricky.
Josh Goldberg
Capital One's tech team isn't just talking.
Rafael Gonzaga
About multi agentic AI.
Josh Goldberg
They already deployed one.
Rafael Gonzaga
It's called Chat concierge and it's simplifying.
Josh Goldberg
Car shop using self reflection and layered.
Rafael Gonzaga
Reasoning with live API checks.
Josh Goldberg
It doesn't just help buyers find a.
Rafael Gonzaga
Car they love, it helps schedule a.
Josh Goldberg
Test drive, get pre approved for financing.
Rafael Gonzaga
And estimate trade in value.
Josh Goldberg
Advanced, intuitive and deployed.
Rafael Gonzaga
That's how they stack. That's technology.
Josh Goldberg
At Capital One, one of the open source projects I work on, someone spent, I think it was about 2,500 words trying to explain to us why we needed to switch from one library to another. That would save about, don't quote me on this, about 104 bytes of node module size and about a fraction of a hundredth of a hundredth of a hundredth of a second of runtime improvement at the beginning, but at the same time, as I'm sure you're going to say within the next 10 minutes, sometimes these optimizations really do result in user line improvements where something that's a fraction of a second faster compounded over time really is better. So how do we know when we're looking at say optimizations in node or use inline libraries? When is it worth it to make that performance performance investments?
Rafael Gonzaga
Okay, it's very important to have baseline, so if you are trying to optimize your code you need to have a benchmark so if you have most of people that use Node js, they use as an HP server. So measure how your routes are responding or how they are performing. If you are getting, I don't know, 10,000 requests per second. If you are getting 100,000 requests per second, measured CPU utilization Measure memory during workload during a benchmark tool. When a benchmark tool runs like Wair K2 or autocannon or Apache, benchmark doesn't really matter. Actually it matters and I can explain a bit more later, but create a baseline. This is the state of art of my HTTP server. Then you start measuring. You can't optimize things without measuring things first. Otherwise you fall into a trick role where you are spending a significant amount of time to get just small milliseconds of improvement, as you said. But there are a lot of improvements you can do mainly when you are comparing some HTTP frameworks. Like most of you use Express because Express is spread everywhere. But what most of you don't know is that if you switch from Express to Fastify, you get a lot of performance. I'm not saying that because I'm part of the FastFi team. I'm also part of the Express performance team. And what I can say that FastFi in the last versions, it's way faster than in, I don't know, a year ago. So always measure. FastFi is still, as far as I know, the fastest framework in terms of stability and performance out there for Node js. And more importantly, make sure that everything that you write to the logs for instance, logs is a huge problem. A lot of people lose a lot of performance by just choosing the wrong log library. People are using console log which is a huge problem. If you are doing that, please stop. People are using, for instance, they are. Winston I wrote an article called the Cost of Logging I believe in 2022 and it is still very popular and still applicable. As far as I know, the fastest logging library out there is Pinot js. The reason for that is that Pinot was writing in a way that it can create a queue of messages and will not block the event loop when writing to the terminal. I wrote in depth about that in that article, so I suggest people to check that it's very easy to find. And Pinot JS also uses Sonic Boon as a dependency, which is very important to make Pinot JS fast. So by choosing the right HTTP framework and the right login library, I'm pretty sure your app will be way faster than nowadays.
Josh Goldberg
One of the advantages, as I understand it of writing things in userland, like for example first Express and then Fastify is that allows users to iterate and experiment. But at the end of the day, some of the things you've alluded to, such as console log being slow, are part of Node Core and therefore the default that a lot of people go with. What would it take for Node itself to have an equivalent to an Express or Fastify or Pinot JS in Core?
Rafael Gonzaga
Okay, the Pinot JS in Core is to. We are discussing that to be honest. So that might happen. Yes. A lot of people ask me why simply Node JS folks can rewrite the HTTP module to to make it similar to Fastify and fast as Fastify. And the reason for that is first one is maintenance. So Fastify, they have a huge team maintaining that. And for Node js, if you move things to Node js, it's expected that you get less contributors working on a specific module because it's way hard to understand Node JS source code than Fastify. The second one is that we can't break the word Node js is used by tons of devices and even releasing things as major server major which is expecting to break. We can't touch very hard on NTP modules because this will migrate people away from Node js. If you look to the recent Node JS downloads dashboard, you see that a lot of people are stuck on Node JS12 just because of breaking change. They don't know how to migrate. It's very hard for them to migrate. And those breaking changes are very crucial for them to stick on an end of life version. And this is a problem because when you stay in an end of life version of Node js, you are not safe. There are plenty of vulnerabilities that affect you. And I also wrote a talk. I have deliver a talk called 5 Ways you could have a Hack Node JS where I expose some vulnerabilities that Node JS have fixed. And if you are using an outdated version of Node js, possibly this will happen to you and that's it. I mean, we can make some improvements to HTTP module, but we can't change it too much. How it was designed is crucial and its legacy first is very hard to change and second, changing that means that you are prone to break a lot of people.
Josh Goldberg
So you have two conflicting desires and needs here. One is you want to keep things stable because breaking changes hurt the community's ability to migrate. But you also want to have modern APIs and improvements. So how do you strike that balance how do you know what's a valid or correct breaking change?
Rafael Gonzaga
To make most of features, they are behind flags, behind enabling flags. For instance, we wrote the permission model. Permission model is a feature where when you enable that, the node js will restrict access to file system, to network, to v8 to v8, inspector protocol, child process worker thread. So all of these will be restricted whenever you pass permission. When you use Node js, this is a security measure and people ask me, why not enable that by default. The reason is that first it will break all the scripts out there, so people will never be able to migrate. People do not read change logs, they just don't want to read that or for some of them is hard. Some of them use Node JS behind the scenes. So for instance, if you are using Next js, you are using node JS behind the scenes. And in some situations you don't have the node JS command out there, it's behind next run or something like that. So this will break frameworks and frameworks will need to upgrade and then users will need to progress the framework's versions to fix that. So it creates a kind of chain of break catch that will reach out to the end users and this will be very difficult for them to migrate. So frameworks will be mad with us, users will be mad with us. And most of the cases, if we enable the permission model by default, a lot of people will just pass disable permission because they don't care about that. So we decide, okay, if people they care about performance, they will opt in. It would be much easier if we rewrite Node JS from scratch. So let's say that we are releasing Node JS 2.0. Possibly those features will be enabled by the foo because we will teach people this is how this Node JS was designed. If you want to use Node js, that's how you go. But since Node JS is still the same, people are just using NVM to upgrade and they don't expect this new design, this new structure. They don't want to learn Node js again, we can't do that.
Josh Goldberg
Yeah, it's also on what's the latest major version at time of recording? 24.10 or so. Or we're not quite at the 2.0 level anymore.
Rafael Gonzaga
Yes, that's correct. I'm working on Node JS 25.0 that will go out in two days.
Josh Goldberg
Oh, well, that's exciting. What are the major changes or features for 25?
Rafael Gonzaga
So one thing important about server major releases a Lot of people believe that several major are the most exciting releases of packages of runtime platforms like Node js, but turns out that it's very very boring. Server Miners goes to Server miners releases performance improvements. They most of the time are categorized as server minor or or Semper patch. Which means that it's very likely that Node JS 24.10 will be way more exciting than 25.0 because 25.0 only contains breaking changes. And for Node JS 25.0 we will have the upgrade version of v8 to the version 14.1 which will bring the major JSON stringify performance improvement. So if we look to the V8 device, they have created a blog post about how they have made JSON stringify fast and with this version of Node JS it will bring the V8 version that includes that performance improvement. We will have a new built in unsigned integer 8 array. It's for base 64 or hexadecimal conversion, WebAssembly and git pipeline optimizations. We are also enabling adding a new feature to the permission model which is the allownet. So network will be restricted whenever you use the permission model on node js25, but other than that we don't have like a lot of features coming in. Most of them they are breaking changes or considerate breaking changes. So if you are using the permission model node js24 it's likely that you get affected by node js25. With this new network restriction we are unflagging the experimental web storage so web storage will be enabled by the full on node js and we are deprecating and removing a lot of APIs APIs that was runtime deprecated, they were removed on node js25 and some of them will be runtime deprecated on node js25. So if your console whenever you run node js and some API is emitting and warning to you that this will be soon removed, possibly node JS25 will break you. So upgrade that.
Josh Goldberg
That is exciting. Removal of dead code, does that impact node performance, download size and so on at all?
Rafael Gonzaga
Yes, I mean we remove code that needs maintenance. So it's for us maintainers, it's very good to remove code.
Josh Goldberg
Is your AI model taking weeks to train or is it too slow for real time inference? Fixstar's AI Booster is the acceleration platform that solves both. AI Booster automatically analyzes and optimizes your entire AI pipeline. The result dramatically faster training, up to five times faster and compute costs slashed by up to 80%. Trusted by major companies including Sony, Honda Mobility. Stop waiting on your hardware. Visit fixedars.com to learn how.
I want to take us a bit back to the second of two scenarios we talked about a performance optimization attempt that ended up showing, well, not always optimal. Is there an upcoming one or a recent change you've made that you're excited about for performance that did work out?
Rafael Gonzaga
There are one that the prequest is to open. I wrote that with Robert will bring a significant performance improvement to the HTTP module of Node js. We talked about that and then I remembered. But it's an opt in feature, so we are releasing that to not break people. It's a new flag. Whenever you create an HTTP server, there is a optimize empty request option. Basically if you are relying on the rest pattern, which is get request should not have a body. Head request should not have a body. If you enable that option, your ATP server will be faster because we'll clean up the string faster. We will dump the string. However, there are people that still read body from get and add requests. So if we enable that by default, we will break those people. Okay, so I believe that we will have that option. We will have some discussions to enable that by default, but this is a separate discussion for now. Let's bring that option. So frameworks like fastfi or Express, they can enable that if they want to. So they will have this gate. If Express enabled that by default and people were not mad with it, it means that Node JS are likely to enable that by the foo as well. So this is a request before you.
Josh Goldberg
Move on, just looking at pull 59778 optimize MP requests, you've got a screenshot in the body of the description showing requests per second and it looks like you're going from in one of the cases, 32,000 to 69,500. That seems like a significant increase in through parts.
Rafael Gonzaga
Yes, that benchmark we have run for 30 seconds with in a dedicated machine. So without this option enable we got 1,000 requests, let's say, or 32,000 requests per second in one percentile to 69,000 in one percentile requests per second. So we are more than doubling down the performance of 8,300. But this is specific to the get and head requests.
Josh Goldberg
It's pretty incredible. You can see how the decision is not easy to make of whether you and when you might want to make the breaking change to turn this on. By default, if you're doubling the request per second, but Also breaking so many people, Surely that's got to be a long, slow deliberating process to turn on.
Rafael Gonzaga
That's correct, yes. And I just saw that they need to rerun CI and land that. This is one of the problems. We run so many CIs in different environments because Node JS runs everywhere. So we have Smart OS, we have Mac OS, we have Windows, different platforms, we have Linux, different platforms. And we need the CI to be green in all duos. I believe that we have more than 60,000 of assertions on Node JS for tests. So it takes a significant amount of time. So to get a green CI it usually gets say, six hours. If you get a flaky test, you need to rerun that. So it takes a while.
Josh Goldberg
Well, okay, you were about to look up some more exciting improvements that you're looking forward to with the next versions of Node.
Rafael Gonzaga
There are some improvements that we did to the Node JS core, but we don't have it optimized on a specific internal code of Node js, so it doesn't translate to an API where people will experience that in real world applications. So there are improvements to the assert partial, deep, strict equal. They are improvements to the how Node JS is benchmarked. So, for instance, people always ask me, if Node JS has so many benchmark files, we have benchmarks for every feature we release, why regressions still exist, why you don't measure benchmark, why you don't run benchmarks after every release or before every release of Node JS to find regressions. The reason is that nowadays to run a full Node JS benchmark CI, it takes 84 hours.
Josh Goldberg
Just 84 hours. Wow.
Rafael Gonzaga
The reason for that is that because measuring JavaScript code is tricky, we can't run a benchmark just once. We rely on an algorithm called Null hypothesis, which tends to be the student test approach, which is we run each benchmark for each configuration 30 times before the change and 30 times after the change. So imagine the situation where in our benchmarks we have configurations. So let's say that we want to create a benchmark file for the U2 inspect or console log better. So we create a configuration where we call console log with a long string, with a short string, with an integer, with an object, with other options like a long object or a small object. So all those are configurations. So we run the benchmark 30 times for each configuration before the change. So 30 times for integer, 30 times for short strings, 30 times for long strings or big strings. And then we run that 30 times again after the change. Then we run, we produce that statistical analysis to prove the variance or if the change, if the performance is statistically significant or not. Because sometimes you run the benchmark before the change just once and run that after the change just once and then you compare. Okay, I got more requests per second second or I got more operations per second, so my code is faster. But that's not the reality. Your machine is doing a lot of things in background. So if you are in a zoom call when you are running a benchmark, it's very likely that your code will produce a lot of variance that will impact in the result. And then the operations per second you get in the end is not true. It doesn't show the reality. Brandon Gregg once did an experiment in 2018, I believe where he shoot in the data center. And then he expressed that the slow disk I O operations increased just because he went right in the front end of the data center and shoot. So this proves the variance. So to calculate if your benchmark produce a statistical significance, which means that if the p value is greater than 0.05, it means your code, they don't belong to the same group, which means your performance improvement is valid or your regression is valid. Otherwise they are just in the same sense of the standard variation. So that's why people normally plot data into a normal distribution. So they measure that. And that's why it takes so long to run benchmarks. But we are improving that, we are creating more machines, we are sharing that, but it will take a while.
Josh Goldberg
That's an incredibly statistical mathematical way to look at this. That must have taken a long time to get to.
Rafael Gonzaga
I love that part. To be honest, most of my research and my studies are about that. So if you look to my blog posts, to my blog in general, I talk a lot about how to prove if your benchmark is valid or not and how to not get tricky. So I wrote talks about that. There's a talk where I created with help of my team, it's called Lies Them Lies and Benchmark which basically shows you why most of the time your benchmark is being lied to you. And this also points to when I was talking about HTTP loading tools. I mentioned that there is no difference between Apache Benchmark or DAPP Work or AutoCannon. But the reality is there is there's a problem when you are using HTTP preload frameworks called coordinate the mission. So jio10 once there is a HTTP load tool called work wrk and jio10 work created a second version a fork of it wrk2 which fixes the coordinate omission. Coordinate omission is simple if you try to explain Imagine that you send a request to your server. Once the server replies back, it will send another request and then it measures the latency. But this doesn't show the reality. Once you send a request, you should send another request after x seconds so it will show the how real world applications behave. Then you get a long latence on the second request because the server is waiting for the second response. So there is a long explanation on the wrk2 repository. I strongly suggest you to test it and it's valid that points a very good solution. So I normally use that for benchmarks in Node js.
Josh Goldberg
Let's talk about your blog a little bit. You are the author of a series the state of Node JS performance. What is the state of Node JS performance? What does that blog post talk about.
Rafael Gonzaga
In 2023 I've been doing Node JS major release for quite a while I believe since Node JS18 or Node JS17 I don't remember I did all Node JS major releases. So Node JS17 18, 2021, 22, 23, 24 and in two days 25 hopefully and I have always wondered, okay, we are releasing a new merger version of Node js. But what this means to performance enthusiasts. It means that if I migrate from node js18 to node js20 my code will run faster. A lot of people don't know that and they create issues on Node JS Core repo After migrating from Node JS 16 to Node JS 18 my application is behaving worse and because benchmarks takes a while, we don't run that very often and we don't have machines or capacity to run that. So Node JS core developers they had to investigate that they need to replicate the environment of the issue. So some of them are only replicable on Windows, some of them are Mac OS and it was very hard. So I decided okay, after releasing Node JS20 I want to know exactly which workload or which APIs will be affected either by regression or by performance improvement. We can't do that as part of Node JS release process because this takes a significant amount of time and on node js 2023 I did using my own time and 2024 I got sponsored by the company I working on to node source so they give me machines to test that dedicated machines time so I could do that and I'm planning to do the 2025 version. So on this report I utilize three versions of Node JS for Node JS 2024 I have used Node JS 20.1, 7.0 and 22 and also comparing to the 18 version of Node JS. So I split the benchmark setup using the Node JS internal benchmark suite which takes the 84 hours and Node JS bench operations which is a repository where I maintain where I also monitor small operations like converting strings using parseint versus plus sign on is that faster on this specific environment? So this repository where I store all those benchmarks and specific APIs for instance HTTP server fast5 and express it got worse or better with this new version because in all major versions of node js we upgrade the V8 version by upgrading the V8 version. We never know exactly which APIs will be affected because it's JavaScript. In the end, if they change something in the git compilation, this might affect the whole EQ system or this might affect just specific operations on Node JS. So for instance the V8 update got the Parsynth performance upper that matches the plus sign. This report it's a more comprehensive study about how the node JS benchmarks are evaluated, how we guarantee we are not measuring non operations and how it will affect you. So for instance by upgrading from Node JS18 to Node JS20 or better from Node JS16 to Node JS20 if you were relying on node js crypto operations, your code will be very slow now because of OpenSSL. So then we track down all Node JS dependencies. Node JS depends on LibUV, depends on OpenSSL, many other dependencies just to know process versions you will see all the dependencies of node js and it got worse because of open ssl. Now it's fixed because we have improved. We have upgraded node js to the open SSL version 5.2 if I'm not wrong and this report contains all the information and all the resources you need to know before upgrading or even to diagnose your Grafana dashboard. Because when people upgrade node JS version they will say okay, my app is now consuming 25% more memory but is using 20% less CPU. Is that better too? And then on this report normally there's a nice explanation and why this is good or why this is bad.
Josh Goldberg
Do you find that people understand the metrics is put forth? Are there ways to kind of convey the nuances and complexities of them that the common node user would understand?
Rafael Gonzaga
The reports I Normally use percentages. So it's easy for them to say, okay, this API is 15% faster or 15% slow. I always create two kind of sections. One for people that just want to get the value and one for people that wants to understand how the benchmark was executed.
Josh Goldberg
That makes sense. Before we move on to the last area of technical topics, I do want to ask about your company, NodeSource, your employer, they sponsor this work. What is it that Nordic Source does?
Rafael Gonzaga
Node Source, it's a computing company, but they also create products. They have an APM which measure the performance all the metrics of your Node JS application without sacrificing the performance. For instance, it's very weird for me as a performance enthusiast that if I want to deploy my application in production and I want to monitor that, I want to measure the performance of my app, this will reduce the performance of my app by 30%. It's weird. It's just bad and solid. A product from Node Source exists. It's an apm. Basically we have forked Node js. We are still rebasing on top of Node js, but we have added or changes that makes APM fast. So now if you don't use APM or use any solid, the performance will be the same. So we have no direct impact in your app. So you'll be able to see in the console CPU utilization, event loop utilization, memory utilization and even creating CPU and heap profiles without losing performance. So you can do all of that in production. So that's why nsolidaz exists and that's why I like it.
Josh Goldberg
Is this something that could be upstream to node as an option?
Rafael Gonzaga
Yes, we do a lot of upstreams to Node js, but we also understand that the process of moving things to Node JS slight slower because it relies. It expects consensus from all members to make some changes and some of them are too business oriented. That doesn't go to the Node JS, but go to a product like NSolid. But yeah, we do a lot of upstream patches.
Josh Goldberg
Great, I'd love to hear that. It's good to see people in the community, companies in the community that not just work around Node but on Node and Init itself to make it better for everyone. Yeah, let's talk at the end of this section about userland libraries. Let's say that I am writing an app and you know I'm using NSOLID for logging and apm. I'm using Fastify rather than than say Express or Core HTTP. What are some of the tips and tricks you'd use or you would give me to make sure my app is fast.
Rafael Gonzaga
Let's say it really depends on the slo or on the expected requests per second you want. I know that a lot of people will say that I want my app to be the fast as possible, but some of them don't need to spend too much time on fine tuning as other companies. So I would say that if you choose a good ATP framework like Fastify and makes a good usage of Fastify, because it's not just using Festify, it's creating fetify routes with the correct expected request objects and expected response objects. So fetify can optimize that it's creating a good pattern of projects. So most of the bottlenecks is in the business code, right? If you receive a request you need to connect to the database, so make sure you have a pool of connections. Measure a code using trace opt and trace theopt to check if you are making use of V8 optimizations. Some people, they don't understand how hiding classes on vat classes makes your code faster. So they are creating an object and using the delete property. For instance, I have an object and I want to delete one property from this object and they use the delete keyword for that. What they don't know is that whenever you use delete keyword the hidden class will go away and this object will be way slower than it should be. So instead of using delete assign the value to undefined so you don't delete the hiding classes. So creating objects using the correct or the expected object tree. So all of this you can get information by using trace deopt. If you get too many optimizations during your code, something is wrong. Make use of a good login library. Whenever you call an API too much, you need to make sure that this API as fast as possible. So v node js is a good logging library. When you create a database connection, make sure that inspect the network Check if you are creating too many sockets. Check if the connection is being up in the pool of connections. So you don't need to create a new connection with database whenever you send a carry for that. So there are more generic performance tips than node js tips I would say so measuring the errors of your machine. So check the events, check syscalls Check if you are using the correct version of node js Please. There is a package I wrote, it's called Is my node vulnerable? So just run your terminal NPX Is my node vulnerable? Is my dash blah blah blah and it will tell you if you are using a server version of Node JS or not. I think upgrading the dependencies is very important. I always suggest to use less dependency as possible. So for instance, if you use U2 StyleText, this replaces some usage of chalk. If you Node JS has now a typescript Node JS has escalate. We have a lot of built in modules that I strongly suggest you to use that because we can make it faster.
Josh Goldberg
What are your thoughts on lock files as applications and as servers?
Rafael Gonzaga
I don't work on products like business products for quite a long time. I have been working with open source or libraries for the last five years, so I don't have a strong opinion on that part. I know as a maintainer that we normally don't use the log files so people can upgrade that. We don't release log files because people can upgrade that. At least this is how we handle that on FastFi and I believe Express as well. So I don't have a strong opinion.
Josh Goldberg
What a rare and beautiful statement from someone who works deeply in tech. I don't have a strong opinion.
Rafael Gonzaga
Yeah.
Josh Goldberg
All right, we're heading towards the end of the interview. Are there any topics you wanted to bring up when it comes to Node or security or performance?
Rafael Gonzaga
Well, if you are interested on Node JS Core and you want to make your contribution, I've been doing live streams on Twitch, YouTube and also X teaching people how to contribute to Node js. So I've been planning to create a live stream during the Node JS25 release to show people how. I release a major version of Node JS and I normally announce the live streams on the Node JS mentoring channel, either on Node JS OpenJS Foundation, Slack or on the Node JS Discord server.
Josh Goldberg
Have you found that a lot of people have started contributing to Node through these live streams?
Rafael Gonzaga
Well, I know at least 10 people that got their first contribution to Node JS with some guidance from the livestream. So it's a very good number for me in a sense.
Josh Goldberg
You've become a 10x developer?
Rafael Gonzaga
Yeah, kind of.
Josh Goldberg
Let's say that I'm somewhat interested. I've never contributed to a major open source project before. I would love to do it. I don't really know what that entails or what the benefits and drawbacks are. How would you pitch this to me?
Rafael Gonzaga
I would say that my career would be way boring if I didn't contribute to open source because it opened so many challenges for me that I could learn a lot. I'm pretty sure that if I haven't started contributing to Node js, I would have stopped my C studies, I would have stopped a lot of performance improvements research I did. So this helps me to find good offers. I have received many, many offers because of my open source work so I could travel through the world. I'm from Brazil and for me to go to Europe is like 12 hours flight and it's very far. I have been in China delivering talks, I have been in the whole Europe delivering talks. And all of these were not possible without my contributions to the open source.
Josh Goldberg
That's lovely. So you've become a member of a global community of people.
Rafael Gonzaga
Yes, I mean I have more people that I know by GitHub handles than in real life.
Josh Goldberg
That's lovely. To close out the interview, I like to ask something explicitly non tech related and that's a great transition. Let's talk about friendships and sports. You used to play tennis and you've recently switched what you've kindly been calling behind the scenes soccer and what others may call football. Can you tell us about that?
Rafael Gonzaga
I have recorded some fire chats at Node Conf I don't know two years ago, three years ago where I told people I have started playing tennis because finding people, finding friends to play soccer, it's way difficult because for tennis I just need to find one person. But for soccer I need to find a whole team. Now after three years I could find a good amount of people and now I'm playing more soccer than tennis. So yeah, I've been playing soccer, I don't know, three times per week as a good Brazilian. So we love soccer, so we do that. It's under my blood. So yeah.
Josh Goldberg
Do you root for any clubs or players still?
Rafael Gonzaga
I support Santos, it's the Neymar team in Brazil. But I mean, we are not good. We are not good now. We are very good, to be honest, but we are not good now. I also like a lot Manchester United, but still it's in the same situation as Santos.
Josh Goldberg
A person must have hope in this world. Well, great, Rafael, you've talked about a lot of incredibly exciting and interesting things. We talked about security in Node, talked about performance, how Node's internal performance works, is improved and has been benchmarked and optimized. We talked about tips for useland libraries and also of course your regular streams where one can learn how to contribute themselves. If we wanted to learn more, if we wanted to reach out to you on the Internet, where would you direct us?
Rafael Gonzaga
Join the Node JS mentoring channel. I'M mostly available on X and also Slack, so if you want send me a message on Slack or Discord, I'm happy to guide you to your first contribution. Also on X, my DMs are open and I'm happy to help.
Josh Goldberg
For Software Engineering Daily, this has been Rafael Gonzaga and Josh Goldberg. Thank you for listening everyone. Have a great day.
Podcast: Software Engineering Daily
Date: December 23, 2025
Host: Josh Goldberg
Guest: Rafael Gonzaga, Principal Open Source Engineer at NodeSource, Node.js TSC member
This episode explores the evolving landscape of Node.js through the insights and experience of Rafael Gonzaga. As a core contributor and leader on both performance and security fronts, Rafael discusses Node.js's progress in performance, benchmarking challenges, userland vs. core decisions, and the community dynamics of major open-source infrastructure. The conversation is technical, practical, and reveals internal reasoning behind key Node.js choices, as well as opportunities for new contributors.
"I have always loved low level programming ... Then I saw, okay, people were running JavaScript in backend. I tried, okay, let's see how it works ... Then I saw the GitHub repository and then okay, they use C so I could help in that part."
— Rafael Gonzaga [03:47]
"A TSC member shouldn't be anything different from a Node JS core collaborator. Anything that a core collaborator does, a TSC can do, and vice versa."
— Rafael Gonzaga [08:36]
"Node JS is way faster than two years ago."
— Rafael Gonzaga [12:37]
"It's very hard to make some comparisons because some API might be fast on your machine ... and with a different workload ... it will cause more de optimizations."
— Rafael Gonzaga [11:35]
"If you are doing that [using console.log for logging], please stop."
— Rafael Gonzaga [18:34]
"We can't break the word. Node js is used by tons of devices ... How it was designed is crucial and its legacy first is very hard to change."
— Rafael Gonzaga [21:36]
"It's very likely that Node JS 24.10 will be way more exciting than 25.0 ... 25.0 only contains breaking changes."
— Rafael Gonzaga [24:58]
"We are more than doubling down the performance ... But this is specific to the get and head requests."
— Rafael Gonzaga [29:48]
"To run a full Node JS benchmark CI, it takes 84 hours."
— Rafael Gonzaga [32:23]
"This report contains all the information and all the resources you need to know before upgrading ... or to diagnose your Grafana dashboard."
— Rafael Gonzaga [41:32]
undefined to deleting properties for V8 hidden class performance (45:02-48:18).npx is-my-node-vulnerable for Node.js version health."[For libraries] We don't release log files because people can upgrade that."
— Rafael Gonzaga [48:46]
"My career would be way boring if I didn't contribute to open source because it opened so many challenges for me that I could learn a lot."
— Rafael Gonzaga [50:13]
"Node JS is way faster than two years ago."
— Rafael Gonzaga [12:37]
"If you are doing that [using console.log], please stop."
— Rafael Gonzaga [18:34]
"To run a full Node JS benchmark CI, it takes 84 hours."
— Rafael Gonzaga [32:23]
"My career would be way boring if I didn't contribute to open source because it opened so many challenges for me that I could learn a lot."
— Rafael Gonzaga [50:13]
| Timestamp | Segment/Topic | |------------|-----------------------------------------------------| | 01:46-03:47| Rafael's introduction and early tech background | | 04:53-07:40| Path from Fastify to Node.js Technical Committee | | 09:29-12:43| Node.js performance evolution | | 12:43-15:35| Benchmarking: pitfalls and lessons | | 16:38-19:39| When is optimization worth it? | | 20:01-22:05| Why Node core can't just "be Fastify or Pinot" | | 24:44-27:04| Node.js 25.0 release: breaking changes vs features | | 28:02-30:32| Doubling HTTP throughput: the empty request flag | | 31:23-37:15| Benchmarking science: repetitions, stats, CI time | | 37:24-42:12| Annual State of Node.js Performance reports | | 42:43-44:34| About NodeSource and nSolid | | 45:02-48:18| Practical performance advice (logging, objects, etc)| | 49:10-49:44| Contributing: livestreams and onboarding | | 50:13-51:19| Personal reflections on open source | | 51:35-52:36| Rafael’s sports & teams | | 53:02 | How to reach Rafael |
This episode delivers a nuanced, insider’s account of Node.js’s ongoing technical and community evolution straight from the core. Rafael emphasizes practical, measurable approaches to performance, the real-world constraints of maintaining a global runtime, and the openness of Node’s community for new contributors. Both the technical depth and community orientation shine, making the episode relevant for Node.js users, maintainers, and open-source newcomers alike.
For in-depth Node.js performance insights and how to get involved, follow Rafael on X (Twitter), or join community channels on Discord and Slack.