Structuring Node.js Applications: Event Loop, Metrics, and Efficient Processing Techniques - JSJ 657
In this episode, they dive deep into the essential practices and principles for successful Node.js development. AJ and Dan are joined by special guests Michael Dawson, James Snell, and Matteo Collina. They bring a wealth of expertise and experience to the table, discussing key topics like experimental tech with existing web standards, managing updates with LTS releases, and the fundamental pillars of Node.js, including the critical concept of "not blocking the event loop."
Show Notes
In this episode, they dive deep into the essential practices and principles for successful Node.js development. AJ and Dan are joined by special guests Michael Dawson, James Snell, and Matteo Collina. They bring a wealth of expertise and experience to the table, discussing key topics like experimental tech with existing web standards, managing updates with LTS releases, and the fundamental pillars of Node.js, including the critical concept of "not blocking the event loop."
They explore the consequences of blocking the event loop, real-world insights into performance issues, and the importance of efficient task handling. They also share their wisdom on utilizing multi-threading, scaling applications, best practices for dependency management, and the significance of regular updates to maintain security and performance.
Additionally, they touch on some fascinating side discussions, such as AI's role in coding, the evolution of package management, and the importance of intentional coding practices. There's even a bit of personal insight with recommendations for exciting Netflix series and real-world anecdotes about Node.js conferences and testing frameworks.
Join them as they unravel these topics and more, guiding you through advanced Node.js
Socials
Links
- The Nine Node Pillars: 9 Principles for Doing Node.js Right in Enterprise Environments
The Nine Node Pillars | 9 principles for doing Node.js right in enterprise environments - YouTube
Picks
- Dan - Monsters: The Lyle and Erik Menendez Story
- Dan - The WordPress drama explained
- Michael - bee-agent-framework
- James - NodeConf EU
Transcript
Dan Shappir [00:00:05]:
Hello, everybody, and welcome to a super exciting episode of JavaScript Jabber. Today on our panel, we have Ajay O'Neil.
AJ O'Neil [00:00:14]:
Yo. Yo. Yo. Coming at you live, healthy, and well from the perfect temperature in the shed. It's been a while.
Dan Shappir [00:00:23]:
And me, I'm your host today, Dan Shapiro from Tel Aviv in Israel. And today, our guests are Matteo Collina. Hi, Matteo.
Matteo Collina [00:00:32]:
Hello. Hi, everyone.
Dan Shappir [00:00:34]:
James Snell. Hi, James. Hello. Hello. And Michael Dawson. Hi, Michael.
Michael Dawson [00:00:40]:
Hi. How are you doing?
Dan Shappir [00:00:42]:
And today, we brought you all over to talk about this excellent article post, you know, that you've written. I loved it very much to the extent that as soon as I saw it, I contacted Matteo and told him, you have to come on our show to talk about this. All you guys out there should also read it regardless of what we talk about it here, and it's called the 9 node pillars. Nine principles for doing Node. Js right in enterprise environments. As I said, this is an awesome article. Who wants to start talking about it?
James Snell [00:01:17]:
So just go read it. I mean, none of those. Yeah. So
Matteo Collina [00:01:20]:
Okay. Let me start. This article starts from an idea of from start from experience. Okay? Start from at the key, the experience of, you know, developers do Node JS all the time. They think they know Node JS, and they don't know know Node JS.
Dan Shappir [00:01:43]:
Okay? That's a pretty unfortunate statement.
Matteo Collina [00:01:46]:
It's No. It's true.
James Snell [00:01:47]:
It's true. It's absolutely true. You know, we Matteo and I, you know, when we the both of our previous employment, we were working doing a lot of consulting work, going out with customers and seeing the same problems over and over and over again. And in every single case, it always came down to folks not really understanding how node worked internally. Like like, you know, what what at you know, how does the event loop work? Those and I things. And
Dan Shappir [00:02:13]:
It just occurred to me that I skipped a very important, point while starting this conversation, and that's, like, who you guys are and why it is that you guys actually do know so much about how node works and how it should be used. So maybe you should you guys should do a brief introduction of yourselves.
James Snell [00:02:36]:
Yeah. Yeah. We can do that. I'm gonna go first and then let
Dan Shappir [00:02:40]:
let you
James Snell [00:02:40]:
guys go go next here. So, James, now I've been you know, I'm currently with Cloudflare. I work on the the the workers' runtime, but, you know, a lot longer than that, I've been involved with Node. Coming up almost on 10 years, involved with Node. And, the at the end of this year, it'll be exactly 10 years. You know, prior to my current employer, you know, you know, Mateo and I were doing all kinds of consulting work, around Node, use of Node, how to do things correctly, help people with performance, performance problems there, having that kind of thing. But, also, just they've been contributing a lot to node. So a lot of the things like the URL, Yeah.
James Snell [00:03:24]:
The original URL parser, not the original one, the
Matteo Collina [00:03:27]:
the the
James Snell [00:03:27]:
web w g, and
Matteo Collina [00:03:29]:
h p two and a bunch
James Snell [00:03:30]:
of other things, that I've been involved with with with adding. So that's me. That's my background.
Dan Shappir [00:03:34]:
Parsing URLs. That must be so easy.
James Snell [00:03:38]:
No. You you can I recommend for for a future episode, get, Yaghi san here? He did the the the ADA URL implementation that Node now uses, and he can tell you why it's not easy at all. So
Dan Shappir [00:03:52]:
Yeah. I know. I was just being facetious.
Michael Dawson [00:03:55]:
Yeah. I'm Michael Dawson. I'm the Node. Js lead for Red Hat and IBM, and I got, you know I've I've I actually got involved in the project around the same time that James has. And so I've been working for a very long time, in the project, a member of the technical steering committee, working a whole bunch of the different, working groups. Particular, like, node add on API is one of the ones that I'm I'm pretty active in in the build working group. And I think back to your earlier question is, like, I think that the challenge is is that you can very easily get get started with Node. Js, but actually getting it right is a little bit more difficult.
Michael Dawson [00:04:31]:
And that's why we we, you know, we see things like some specific guidance can really help people going forward. Over to Matteo.
Matteo Collina [00:04:38]:
So hi. Hi, folks. I am a little bit under the weather today, so I'm sorry. I didn't want to to to defer the the recording. So so sorry if I'm less, I don't know, excited as usual.
Dan Shappir [00:04:53]:
Very well.
Matteo Collina [00:04:54]:
It's, look. Well, I, well, I have I have a at this point, I've been doing doing Node. Js for a long time. I have accumulated, a few 100, NPM deploy a few 100, modules on NPM, which more or less total, a very nice 1%, close to 1% of the total number of down of downloads of MPM itself. Wow. It's it's a little bit unbelievable, to be honest. The numbers are, you know, it has way too many zeros in them. Okay?
Dan Shappir [00:05:31]:
You've been busy.
Matteo Collina [00:05:33]:
Me. Well, yeah. Everybody seems to love the the code that I push that they push out for free. So, anyway, few years back, I started this company called Platformatic to, you know, to push Node to the next level. And that's where what we are trying to do. And, and we have been trying to fund some of those initiatives and things and promote, Node. Js. So here we are.
Dan Shappir [00:06:06]:
Cool. Now you guys all work at different companies. So you're obviously all 3 of you very much involved in Node, but your day job is at different places. How did it happen that all of the 3 of you came together to write this article?
Matteo Collina [00:06:22]:
Oh, I can take this. So, basically, it's actually one person that is missing in this call, which is Natalia that was also part of the review. Okay? And Natalia is also the lead owner and for JavaScript, DX and DevTools for Azure. And the 4 of us like, this started from my ID for from, an idea that I had a few months back and says, look. How come we can how can we promote and solidify that knowledge? Okay? And how can we, stop start pushing back against the, all the bad tutorials, all the bad all the bad practices that are out there and plugging every single Node. Js code base that I have that I have seen. K? Because it that's that's frankly what it is. So, at that time, I started looking and said that I pinged a few friends and decided, look.
Matteo Collina [00:07:20]:
Who can who can I ask? I want representation for a bunch of different companies and so on. So and let's try to put the our our minds together and write something up that can be, that, you know, we can be happy with and can help developers, you know, you're doing Node. Js well and stop those, you know, spaghetti's code mess that they do most of the time.
Dan Shappir [00:07:53]:
So
James Snell [00:07:53]:
Yeah. And one one important point for me is, like, none of none of the information in this blog post is new. It's stuff that we've talked about in in talks over the years for conferences and workshops, and,
Matteo Collina [00:08:05]:
you know, each of us in in
James Snell [00:08:06]:
in various ways have have talked about these things before. Unfortunately, a lot of that gets kinda washed out in the noise of, like, you know, there's so many of these, tutorials that just kinda get things wrong, and it ends up washing out the the the good information, you know, just kinda in that noise. And so it's like is is many times we can repeat this stuff, get it out there. Like, you know, I'd like to see us, like, repeat this again, like, a a year from now. Just kinda keep reiterating on it. Keep going. This is not the obvious
Dan Shappir [00:08:38]:
gets on again and again in the future. Individually or altogether, just say the word. Obviously, we will enumerate through the pillars and look talk about the positive stuff and the things that that need that should be done and can be done and need to be done. But to make it spicy, I do actually want to start with some of the negatives, if you don't mind. You guys said that you encounter so many bad practices and so much bad advice and bad code. And without naming names, can you give some examples?
James Snell [00:09:17]:
Oh, yeah. We can do whole whole examples. I'm gonna Oh, we can do ago, I did talk.
Matteo Collina [00:09:22]:
Oh, go ahead, James.
Dan Shappir [00:09:23]:
This is a
James Snell [00:09:23]:
couple years ago, I did a talk called broken promises. There there's you can you can find it on on YouTube, and I, you know, created with the work some workshops. Just that, you know, kind of breaks down some of the really bad ways people just get things wrong, particularly around promises because they just don't understand how they work. I had one former consulting customer. When I walked in, was doing a workshop, their their their lead engineer on the team started arguing, with me because he believed that creating new promise was just like creating new thread in Java. So, no, it's completely different model. And this was their lead engineer on on on the team, because they just did not understand, you know, how how this works, and I we just we just kept encountering that over and over and over again, that kind of stuff.
Dan Shappir [00:10:14]:
I just posted the link, by the way. I will also put it in the show notes through that talk.
Michael Dawson [00:10:21]:
So
Dan Shappir [00:10:21]:
Yeah. That's that's pretty amazing. Like, I can understand why somebody might confuse a worker with a thread, but confusing a promise with a thread, that's pretty extreme.
Matteo Collina [00:10:32]:
But look, we can even go to more of a way more basic stuff. K? Mhmm. Like Yeah. Like the let's let's talk a little bit about updating Node. Js. Update do not use, deprecated code. It's unbelievable. Okay?
Dan Shappir [00:10:52]:
The Yeah.
Matteo Collina [00:10:52]:
Companies are not updating Node JS. Like, this seems you know, it's it's bizarre.
AJ O'Neil [00:10:59]:
Once once you deploy something though, it's working, just let it be. Right? I mean, I know a lot of companies are, you know, in some sort of hype cycle where they're just deploying the latest framework every other day, but I think a lot of profitable companies are creating a product. And once that product is good, they're not they're not gonna, you know, rock the boat on it every 5 minutes. They're gonna let it cook.
Dan Shappir [00:11:24]:
Also, you know that old joke about that the developer and his, son walking down the road, and the the the boy says, dad, why does the sun rise in the east? And the father says, it works. Don't touch it.
Matteo Collina [00:11:43]:
Those are good points. Those are good points. But, you know, no one wants to use software that is full of security vulnerabilities.
AJ O'Neil [00:11:52]:
Well, maybe they should stop putting them in node.
Matteo Collina [00:11:57]:
Oh, maybe they should stop putting their products on the Internet then. That's a pretty eastern way to you'd be pulling the plug. It's it's it's secure by default. Okay? Tell
James Snell [00:12:09]:
me so so an application an an application that that has proper isolation around it. And I'd say, if all of the routes coming into that thing are secured and it's not exposed to the Internet, it's just like a long running enterprise application that's there to support existing business processes. If they don't update, they don't update. That doesn't matter because be because they have that isolation and the the the types of threats that are coming at that server, you know, are are much more limited. But if something's out on the Internet, if it's exposed to the Internet, you know, you don't want to have software running that has these security vulnerabilities. You really should update. And as updating, it you know, you can't just quite throw a new version out there. You need to see what other changes are going on.
James Snell [00:12:53]:
Like, we'll deprecate things that we real people really should not use because it could be a security vulnerability, but we you know, but removing it or changing the way it works is too much of a breaking change. And we don't wanna force a breaking change on people. We just wanna strongly nudge you away. Right?
Dan Shappir [00:13:11]:
Yeah. Also, it's not as if those organizations aren't updating their own code. I mean, you know, if if the project is dead, then it's dead. But, you know, we are primarily talking about, you know, living software needed.
AJ O'Neil [00:13:25]:
Dead, profitable. There's a difference between dead and In order to be profitable It's not a suck of engineering resources every week. It's actually making money.
Dan Shappir [00:13:36]:
Yeah. But in order to be profitable these days, you need to be a service. And the only way to justify being a service is continuously releasing updates even if nobody asks for them.
AJ O'Neil [00:13:47]:
Well, I I I was gonna say one thing that circling back. I don't think I have seen anything break in Node since version either 10 or 12. So I recently updated an application. I was so afraid because I'm actually using private APIs in the networking layer. I updated an application, I think, from it was version maybe 12 or 14 all the way up to version 20, and there were no issues. So Node has become incredibly stable probably after version I wanna say after version 10. I think there was a ton of breaking changes in the version 6 or 8. But version 10 or 12, it's it's been incredibly stable, and the likelihood that you'll have to go debug things is is unless you're using an experimental feature, you had experimental flags.
AJ O'Neil [00:14:37]:
But even then, I don't think I've seen any breaks in the experimental features, in in the last several years.
James Snell [00:14:43]:
There's a few. They yeah. They're a few. They come they you know, they're they're usually pretty small, but they they they happen every now and then.
Michael Dawson [00:14:48]:
It it is None of
AJ O'Neil [00:14:49]:
the ones that I use, like Fetch and the there was something in, Web Crypto. And maybe there's some more niche things that are weird like the, what was that it's like a Lifetime's thing. I forget what the name of it was. If it I don't know if it's still a thing, but there was, like, a some sort of a Lifetime y thing.
James Snell [00:15:08]:
And and party
Michael Dawson [00:15:09]:
seem to be party yeah.
James Snell [00:15:11]:
Yeah. Everything about async though too.
AJ O'Neil [00:15:13]:
That that might be like, there's some of that stuff that was super experimental I didn't touch, but anything that already had a web standard was the stuff that I was that that I've been using that's been experimental. It's certainly
Michael Dawson [00:15:24]:
like if you follow the discussions in the in the project, we really are careful about that, and we think carefully. And, you know, if even the ones that James mentioned, we do make some small breaking changes, but we think very carefully about those. We try and understand the impact. And so, yeah, I I think that's one of the things the project has been doing quite well over the last number of years is to try and minimize that. The other thing I wanted to add to what James was saying is, like, it really comes back to risk management. You know, you you can continue to run on older versions, and I think if you've done your risk management, you've done your analysis, like, you may, you know again, back to your point of, like, it doesn't cost any money to leave it just running. So that that isn't that is good. And if you've actually thought about it, maybe you're doing the right thing.
Michael Dawson [00:16:08]:
I think we just don't necessarily see that people are, like, thinking about it enough in terms of, like, should I should I have updated? You know, that's the easy answer is if you you stay on the if you're gonna get the security fixes, or, you know, there's some companies like like the one I work for that will give you longer term support, so you're probably okay then. But, like, we'd probably like to see a few more people either very carefully looking at the risks or sticking to the LTS releases and the ones that are active because those are the ones that, like, the project is gonna help.
Dan Shappir [00:16:40]:
Yeah. But now you're starting to go towards the actual pillars because that's literally one of the pillars. Mhmm. So, I'll just pull us or push us towards that, and let's maybe start going down the pillars unless you guys want to mention something else before we we we do that. Okay. Let's start with the pillars then. So pillar number 1, do not block the event loop. That's an interesting one because it's actually also very much pertinent to the browser, not only to Node.
Dan Shappir [00:17:17]:
And, actually, it's also pertinent to the, Deno and BUN. By the way, I will say that quite a number of these pillars are relevant, or almost all of them are also relevant to Dino and to Bun, I I think.
Michael Dawson [00:17:31]:
Mhmm.
Dan Shappir [00:17:32]:
And some of them are relevant, you know, to whatever server platform almost you're using. You know, they might be relevant if you're using Java or Go or whatever. But, again, we'll be focusing on a node in this conversation. So, again, the first one is do not block the event loop. We've discussed the event loop in the past on this podcast, but maybe it's worthwhile for one of you guys to quickly reexplain or reiterate what the event loop is and why it's so important not to block it. Yeah. I mean, we can can talk about
James Snell [00:18:08]:
it just in very, you know, very high level general terms. You know? You know, a node has its event loop, which is based on libuv. It is structured a particular way. Deno and and and Bon and workers, and so we you know, they all have event loops that are they work slightly differently. They have different phases, different, you know, slight you know, slightly different implementations. So they all work slightly differently, but they all have the same fundamental concept of it's gonna be monitoring the system for, well, you know, certain events, IO, hey. I wanna read a file or I've got a network connection or whatever. And as it's turning, it's gonna, you know, say, oh, I gotta I got some IO.
James Snell [00:18:49]:
I'm gonna fire a callback. That callback is gonna go off and run some JavaScript and what's important to understand is that while that JavaScript is running the event loop is not it pauses while you go off and run that JavaScript and then when that is done running, it comes back and the loop continues. It doesn't matter what platform you're on. That's how it works. Unless you're using worker threads, but you have multiple event loops running on different threads, when you're whenever you're running JavaScript, nothing else is running. Right? You're not going out and pulling IO. You're not, you know, looking for you
Matteo Collina [00:19:23]:
know,
James Snell [00:19:23]:
you can't go off and accept a new connection. Yeah. That kind of stuff. Right? So it you know, it's you have to make sure that that JavaScript that you're running can return fast enough for that event loop to turn around and and do something
Dan Shappir [00:19:38]:
else. Now on the browser side, it's it's maybe less catastrophic, but it's often more obvious when there's a problem with the event loop because user interaction starts to get junky. Somebody clicks a button, and, the UI doesn't respond because the browser is too busy processing the JavaScript for a previous event. What's the negative impact in node when you, don't process stuff out of the event loop quickly enough or when things stay in the queue for too long?
Matteo Collina [00:20:19]:
I have a very nice talk on this, okay, which I recommend everybody to watch. I'm going to pass it. I'm going to summarize and then pass it into into the chat for everybody to, to to take a look. Okay? So the, the gist is is very simple. What is that? What happens? Okay? You take, the event group is be gets busy. Okay? The problem, it doesn't you say, well, the event group is busy. What problem it can be? Okay? Well, generically, if there's only one user, k, which is, for example, the case for, deployment on workers or an AWS Lambda, this is essentially the impact is very limited. Okay? However, you are also missing out on the key feature of Node.
Matteo Collina [00:21:14]:
Js and JavaScript itself because you can, you know, supporting multiples at the same time allow you to maximize the use of the resource of that single process. So what happens is that once the amount of load goes over, and there's a little bit of math involved, goes over a shared threshold, The response time of your application will start getting, will will start looping into we start growing in an exponential in a in an exponential fashion. And therefore, at that point, you are your application will stall completely very quickly and not responding, not nothing, spinning wheels. Typically, the problem is if I send a request, okay, to you, you want the you if you are if you're done a good job, you are going to respond your server is going to respond in, I don't know, 200 millisecond, a second, 2 second. Okay? After what's the threshold after which I stop responding? Okay. I stopped I stopped waiting for a response. Okay? But the problem is then when you receive an an HTTP request in node, you you know, Node. Js has received that request, and we continue processing that request up independently of the fact that the of the user on the other end as, is still there.
Matteo Collina [00:22:46]:
Okay? You can detect that. You can handle this with our signals and a bunch of other stuff, but it Yeah. Definitely not
James Snell [00:22:55]:
Yeah.
Matteo Collina [00:22:56]:
Definitely not common. Okay? So and the the genetic result is and when you Node. Js reach a certain level of load, it become very much unresponsible. The your application become unresponsive completely. And this is a massive, massive problem.
James Snell [00:23:13]:
A great example. You know, based on former customer, I'm not gonna name any names and such, but we were we were called out to do some consulting work for them because their node application was very, very slow. They were getting a whopping 4 requests per second production. Like, what the hell are you doing to get only to only get 4 requests per second? Well, what they were doing They're
Dan Shappir [00:23:35]:
calculating pi to the trillionth digit digit on every request.
James Snell [00:23:41]:
Almost worse. So, they they were using an old version of Apollo, that was not very, performance optimized. Every GraphQL query that they would receive was very complex, and it ended up being where they would do, like, 5th 10 to 15 sub requests on the back end. That, back then, the way that Apollo works is it would receive the request, it would parse it, generate the AST, walk the AST, go off and submit all of the, sub requests, wait for those to return, and then would have to go through and do this this process of reconstructing the response. Unfortunately, these these queries were so complex that it was blocking the event loop. All of that processing was was synchronous. Alright? Now waiting on the sub requests, that was asynchronous, The actual parsing and walking of the AST was fully synchronous, and they were blocking the event loop from progressing every time that happened. And they were blocking it by so much that, you know, it couldn't get around to take the next request.
James Snell [00:24:39]:
Right? The other problem they were encountering though is roughly maybe about 15% of their, of their requests were failing with timeouts. I'm like, you know, we don't we don't understand why these are failing with timeouts. Well, what would happen is they would send, like I said, 10 to 15 back end requests. Right? You know, sub requests. Those would go to the back end systems. Those systems were responding quickly. Right? And and and and, you know, having, responses pending in the IO queue, in in in the the node event loop. But if you look at the phases of the node event loop, what you'll see is almost right before we poll for a pending IO, we we check timers.
James Snell [00:25:25]:
Right? You know, in in that loop, we always check timers first. What was happening is that the event loop was being blocked for so long that by the time the event loop turned and came to, and broke the timers, even though that those responses the sub request responses were waiting to be read, the timeouts on the sub requests would would fire and cancel the entire thing.
Dan Shappir [00:25:47]:
Oh, no. So it
James Snell [00:25:49]:
was just like this compounding problem that all of this synchronous activity blocking the loop from actually advancing IO tripping itself up.
Dan Shappir [00:26:00]:
If I'm thinking about it, I can basically, like, perceive of 2, like, main problematic scenarios here, and correct me if I'm if I'm wrong. One scenario is that even though events are pre are being handled relatively in a timely fashion individually, the rate in which they're coming in is so high that, the, server is simply unable to complete the processing the events at the rate that new events are coming in. That's that's problem number 1. And problem number 2 is that regardless of the rate that events are coming in, sometimes the processing is so lengthy that the loop is just being blocked for so long that it's making the system and the system is unresponsive during that time, that that causes problems because other events time out or not processed in a sufficiently timely fashion, all sorts of problems. So the the the service might be even mostly not busy at all, but whenever something comes in, it just gets stuck for for for too long a period. Am I understanding correctly?
Matteo Collina [00:27:20]:
Yes. Yes. Yes. And if that event opens happens too often, it gets into a catastrophic failure. And most node go ahead, Michael.
Michael Dawson [00:27:32]:
I was gonna say, like, the the event loop's really optimized to do lots of short things. And, you know, you you talked about the first case of things coming in too quickly. Well, may node can scale to take a lot of incoming requests as long as you quickly hand them off to something else to, like, you know, if you come in, you take a request, you hand it off to the database, and you do that asynchronously, it can scale to lots and lots of things coming in.
James Snell [00:27:57]:
And
Michael Dawson [00:27:57]:
I think as as Mateo was kinda saying, but if you get to a point where you're you're trying to do too much in the event loop itself because you're you're effectively sharing a single thread, you're now gonna slow everything down and it it falls over a cliff at at one point.
James Snell [00:28:13]:
So, you
Michael Dawson [00:28:13]:
know, if you've got longer running tasks, you really wanna push them to worker threads. And a good example that I I I I think is Or to other servers. Or to yeah. Or to other servers, but
Dan Shappir [00:28:23]:
Like a microservices architecture or something.
Michael Dawson [00:28:26]:
Exactly. The The the one thing I think is kind of interesting is even if you have your microservice, you say, okay, I'm gonna make a microservice for my very long running job. You still don't wanna block the event loop for that microservice because the main event loop, because, well, what if you deploy that microservice to Kubernetes? Kubernetes is probably gonna have a liveness check. And, well, how is that liveness check gonna run? It's gonna have to hit that main event loop and say, hey. Are you still alive? And if
Dan Shappir [00:28:52]:
you don't Sorry. I literally had this problem. Okay. Yeah. At the company that I worked at, again, without naming names, we were actually using, Prometheus, the Prometheus client. And without going into reasons, the Prometheus response that was being generated was huge, and it was a huge string being serialized. And that just took too long. And if that happened while the liveness check happened to come in, it could literally cause the liveness check to time out and cause Kubernetes to kill that instance.
Michael Dawson [00:29:33]:
Yep. Mhmm. So you you always wanna push your long running jobs onto worker threads so that your main event loop can respond quickly. Yep.
James Snell [00:29:46]:
And this problem is is not unique to Node. Not by any stretch. Now in other run times, it manifests differently. Like workers, you know, we have a completely different threading model and workers to know. Every request is basically running on its own thread coming in, we can still accept other requests and that kind of thing. But, an isolate, a particular worker might be used by multiple threads. So whenever one request is being processed on one thread, right, no other threads can use that isolate that can can use that, you know, that particular instance, and we have to share these. So we have these things that are called, you know, basically lock contention.
James Snell [00:30:25]:
It's waiting for that locks you know, waiting for that isolate to be free so I can use it on this particular thread, and it jumps around. If it it's a different mechanism, but has the same effect of blocking other things. If one particular request has too much synchronous processing that goes on for too long, then other threads can't acquire that lock and can't progress. They can't, you know, run their own JavaScript, and and it ends up being the same basic effects block in the node event loop. So you just gotta
Dan Shappir [00:30:55]:
remember think about lock soft and sorry. You just just just that I'm I'm not used to thinking about locks so often in the context of JavaScript. That's all I wanted to say.
James Snell [00:31:05]:
Yeah. I mean, what what they're there, you know. And and and the the key concept here for this particular pillar is, yes, run JavaScript all you want. Just do it in short span. You know? Short first. Don't do these huge, long, synchronous processes.
Dan Shappir [00:31:19]:
So, basically, either push processing off of the main node thread to workers, to microservices, whatever. Don't and don't wait on them. Just send it and wait for their synchronous response, or break your, long running JavaScript into multiple shorter segments. Like, it might be anything you know, the the set time out 0 for the win.
Matteo Collina [00:31:50]:
The setting mediate, typically, the task that the the company
Dan Shappir [00:31:53]:
is doing.
Matteo Collina [00:31:55]:
But yes. Unfortunately, yes. Okay? In that way, other things can be scheduled in between. K? So that's the gist. But, genetically, I would say that we do have enough fake technologies right now to run things easily on worker threads that you should just be using threads. Like, literally, most developers don't think, that Node. Js is multi threaded these days. It has been since 2018, and most developers thinks, you know, they're still reading that tutorial for 2015.
Matteo Collina [00:32:27]:
So, that's a problem. I have to say that there is one issue with
Dan Shappir [00:32:33]:
it, and I know that there are several proposals that are looking to address it. But so far, it still exists, and it's more of a Java script issue than a node issue, and it's that serializing stuff across workers can be sometimes more expensive than the actual work that was offloaded. Like, serializing and deserializing each way can sometimes be more expensive than the actual work that you offloaded if you're not careful.
Matteo Collina [00:33:05]:
Of course. But it it means that you need to offload stuff that is bigger, essentially.
Michael Dawson [00:33:10]:
Yeah. Yes. And and there and
James Snell [00:33:11]:
there are ways around that, you know, with with, you know, like, shared array buffer and some of the shared data structures we have. So
AJ O'Neil [00:33:17]:
Yeah. So Node has the ability to run multiple processes. So you can you can fork and you can I don't remember exactly I kind of forgot it because it turned out not to be useful for this very reason that the the communication between node processes of doing the JSON stringify and the JSON parse makes it so that you should probably never ever do that? And the only way that you should be using node, if you're gonna use multiple processes, not is not its its child process forking mechanism, but rather, you just run multiple processes. They handle multiple requests and let them, you know, do Depends on everything. Database separately and stuff. Yeah. What where where would that where would that be profitable? Where where would it actually make sense to use that oh, cluster. It's called node cluster.
AJ O'Neil [00:34:10]:
Right?
Michael Dawson [00:34:11]:
Yep. Is that what it's called? Yeah.
AJ O'Neil [00:34:13]:
Yeah. I think it's kind of a secure feature most people know about.
Michael Dawson [00:34:17]:
Yeah. I think today,
James Snell [00:34:18]:
I would you're doing. Okay.
Michael Dawson [00:34:20]:
I was gonna say, I today, I would defer to other things like, you know, Kubernetes will manage multiple instances of your node application, each which should be stateless. So, like, if you wanna scale, there's lots of non node specific ways of scaling processes out so you can have multiple copies of your your micro ins of your micro service. So that's why I wouldn't necessarily be using the cluster module on its own anymore. Yeah. So it's really like, you know, I would typically scale using those technologies when it's a matter of just needing more than one thread's worth worth of, you know, throughput. Because you could have lots of little tasks, but you just still can't handle all those tasks on on a single thread, in which case, let's scale out to multiple processes. But if you have long running tasks, even if you have enough to to maybe only take 50% of your your single CPU, you don't wanna do those on your main thread loop. You wanna still push those to workers because
Dan Shappir [00:35:14]:
you
Michael Dawson [00:35:14]:
don't wanna be blocking all the all the work based on those lower or longer transactions. Right? Even if there's, like, 1 in 10, every 10th second, you don't wanna have something that takes a really long time and slows everybody down.
Dan Shappir [00:35:26]:
Yeah. I think it was Jake Archibald that said it in the context or maybe it was, Surma that said it in the context of browsers that one of the reasons that you want to offload things to workers is not so much sorry about performance. It's more about consistency, that you don't want all of it. Yeah. Like, every x task to suddenly block your system for too long. I do have to say, though, that in my experience, most of the work that I've seen done on node is mostly as quote, unquote, middleware. So very often, there's no no so much heavy lifting being done inside the node service itself. Let's say it this way.
Matteo Collina [00:36:05]:
Are you sure, Dan?
James Snell [00:36:08]:
No. I'm not. Now I'm scared.
Matteo Collina [00:36:10]:
Like, let's let's if you if you take a look at what the, all the front end meta frameworks are doing Mhmm. Lately, they all of them, they are massively blocking the event loop. Like, they
Dan Shappir [00:36:27]:
simply because of all the all of the rendering code, the all the service that rendering stuff?
Matteo Collina [00:36:33]:
Yes. So in that scenario, if you're ready, I have a very expensive rendering pipeline, and you also need to do some, data processing, data mangling that can take some CPU time, you are really, really you really, really want to push it somewhere else. K?
Dan Shappir [00:36:52]:
And do they? Well,
Matteo Collina [00:36:56]:
not on the not on the tutorials, but, yeah, you can, But not on the main to not on the main to do.
Dan Shappir [00:37:01]:
No. I'm asking if from your experience, the framework makers are doing the the the best, you know, the best that they could do to offload stuff.
Matteo Collina [00:37:12]:
No. They they are in in order
James Snell [00:37:14]:
to to let me get better.
Matteo Collina [00:37:16]:
It's it's getting better and better and better. And I think it's it's not like, a lot of it comes around on the marketing side versus the framework itself. Okay? Then nothing in the frameworks blocks you to do certain things. Okay? But it's more about how they market the the the frameworks and the products that cause like, they they make, the they make those applications. You know? They teach developers using their frameworks very often that they could do certain things, and those certain things will work very well up until a point. And then it what they won't work anymore. But they then don't tell you that point.
Dan Shappir [00:37:57]:
Yeah. And and the Prometheus example I think I gave is is a pretty good representation of that.
Matteo Collina [00:38:03]:
Yeah. For for that, okay, what we have recently been done in, we have launched a product called the Vat application server. And what we do is we keep we use one worker thread. So we run the applications in in the application in a worker thread, and we keep the Prometheus in the main thread. So in this way, we can have the monitor. Okay, not affected by the, the application itself. And in this way, you can keep things, we can keep things responsive and up. Okay? And and be able to monitor them correctly even if the application is under heavy load.
Dan Shappir [00:38:46]:
Yeah. By the way, just to toot my own horn, I actually contributed back into the prompt client project and optimization that basically just reduced the the runtime cost of of serializing the string by something like 50%. So
Matteo Collina [00:39:00]:
Good. Thank you.
James Snell [00:39:01]:
That serialization thing. And going back to, you know, AJ's, you know, original point there about the cost of serializing the data back and forth across these boundaries. Alright. You know, it doesn't matter if you're using a worker thread or a a child process or whatever. IPC, it doesn't matter. Serialization and deserialization, back and forth, those boundaries always has a cost. You can use, you know, faster serialization frameworks, so protobuf for CAP and p versus you know, instead of serializing everything as is is JSON, but you're still going to have a cost. So it's like anytime you're you're distributing this load, you you need to do you know, take effort, take steps to minimize the amount of serialization, deserialization you're gonna do.
James Snell [00:39:42]:
If you're using a child process, rather than sending a a large chunk of JSON, just pass the FD. Right? And let the let that child process, you know, read the data off the, off the network and do its own, you know, some parsing or whatever. If you're doing worker threads, use shared data objects like shared array buffer rather than things that need to get copied and serialized using, you know, structured clone. The more of those kind of things you do, the more effective this this load distribution is going to be because you're not gonna eat the you know, eat eat up all your your performance gain on serialization, deserialization cost.
Dan Shappir [00:40:18]:
So We've been stuck on the first pillar for such a long time. It's pretty obvious we won't be able to run through all the pillars, which is just a great excuse to to invite you all over again. But still, unless somebody else wants to say something about the first pillar, I think we'll move on to the second one. Is that okay with the I think
Matteo Collina [00:40:37]:
we have covered the second one too. You know? Yeah. We have. Yeah.
Dan Shappir [00:40:41]:
Yeah. To an extent, we have. It's, monitor note specific metrics and act on them. This is one of those recommendations which is true everywhere, for every system, not just for node.
James Snell [00:40:53]:
It's I I will say that be monitoring. Yeah. I don't see on this particular pillar. There there there's there's one here that is worth calling out that most people, most node users, even even the long term ones, aren't familiar with. Event loop utilization. Folks still talk about event loop delay. Right? And that is a different metric. Event loop utilization is a relatively new concept.
James Snell [00:41:15]:
It's it's been there for a couple years. Most people don't know about it. And it it's a measure how it's
Matteo Collina [00:41:20]:
4, James. Yeah. Maybe 4.
James Snell [00:41:21]:
Yeah. The event loop utilization is a measurement of how effectively your event loop is processing tasks, versus waiting for things. And it's it's a much more accurate metric of how, well your application is performing than event loop delay. So everyone
Dan Shappir [00:41:41]:
really should be Before you continue yeah. Because I would like you to explain it. I'm familiar with the term with the metric called event loop lag. Is that just an alternate name for event loop delay?
James Snell [00:41:54]:
Yeah. That that I would think so. Yeah.
Dan Shappir [00:41:58]:
So event loop lag, which I knew, was basically what you described. It's the like, looking at the meantime or the 90th percentile between when an event gets into the queue and until it gets processed pulled from the queue in order to be processed. And, obviously, there, the statement was, you know, you want the mean value or the 90th percentile or whatever to be basically as low as possible in order for the system to be responsive. But you're talking about something else. You're talking about event loop utilization. Can you explain that metric to us?
Matteo Collina [00:42:34]:
Yeah. I mean, there there's a
James Snell [00:42:36]:
a a few things that go into it, but it's basically a ratio of how how much time your event loop is spending doing things versus just sitting idle waiting for things. So let's say if you have an, event loop that is just going off your application is just going off and scheduling a whole bunch of IO, and then it has to wait a long time for that IO to do anything. And in between those times, it's not actually processing anything else. Right? In that case, your event loop is not being utilized effectively. It's spending most of its time being idle waiting for stuff. But if that event loop is able to turn over very, very quickly, accept a new request accept a new request while it's processing other things, While it's waiting for that other stuff to happen, if it's able to keep processing things, then you're gonna see a higher utilization. That basically means your event loop is is doing more, more efficiently. I hope that's very there's a whole Yeah.
James Snell [00:43:36]:
Whole paper on it.
Dan Shappir [00:43:38]:
Okay. But I I'd be happy to have a link to that paper, but one thing does concern me. It does seem that if I pull in, like, the first event and that triggers an infinite computation, which means all the other things are just stuck in the queue forever, my event loop utilization would still appear to be great because I'm just processing forever. Like, is that am I or am I missing something?
Matteo Collina [00:44:06]:
Yeah. The the missing some of
James Snell [00:44:08]:
the details. It it takes some of those those things into consideration. The the paper goes into a lot more detail, and this was done by Trevor Norris, at NodeSource. The the the the blog post he wrote on this initially, introducing it answers pretty much all the questions about it. Right? It it is one of the best research paper
Matteo Collina [00:44:26]:
Consider the you can you can take, event loop utilization in in a slightly different way. Okay? Consider this. At event loop delay or event loop lag, k, it's a metric, k, that you can measure after there is a lag. Okay? Mhmm. However, you only have a lag, okay, if your event loop is very busy.
Dan Shappir [00:44:49]:
Correct.
Matteo Collina [00:44:50]:
Okay? Event loop utilization is able to tell you that the event your event loop is getting busy. So you can act on it way sooner than than the event loop lag. Okay? In fact, it's a much
Dan Shappir [00:45:05]:
Basically, what you're saying what you're saying, if I'm taking too long to process user requests, but I have very few users, then I might not notice that I have a problem. And by the time I I do realize I have a problem, it's kind of too late in a sense because users are already suffering.
Matteo Collina [00:45:23]:
Yeah.
Dan Shappir [00:45:23]:
What you're saying is with event loop utilization, I'll be noticing it much earlier and be able to respond to it, you know, in advance. That's really interesting. I I very much would like to look at the paper.
Matteo Collina [00:45:37]:
It's,
James Snell [00:45:38]:
the other the other thing that it does
Matteo Collina [00:45:40]:
Go ahead, James.
James Snell [00:45:41]:
I'll just mention real quick. The other thing that it does is it tells you how well you're scaling, and it gives you a much more accurate scaling point. So, a lot of applications previously would look at CPU usage. Right. And when when node process is primarily just one thread, one main application thread before, we had worker threads, That was an okay measurement, but it was still pretty noisy. As soon as we introduce worker threads, the CPU monitoring just goes out the window because it becomes way too noisy because you're, you know, because it's it's not fine grained enough to be able to show you individual event loop processes. The event loop utilization is per event loop, so it's per worker thread, and it gives you a much better signal at where you where and when you need to start scaling your application to multiple processes and multiple worker threads. You know you know, better than any other metric that I've seen, this is the one that gives you the the the the best accuracy for that.
Dan Shappir [00:46:41]:
And monitoring systems these days, do they expose this metric?
Matteo Collina [00:46:47]:
Well, platformmatic does. So if you sorry for the for the pun here, but, yeah, we our product our our initial product, absolutely. But also all our open source expose this metric on as part of the Prometheus integration. So you can essentially take it and consume it and so on and so forth. The important part is that you want you want to, set your outer scale to, look at this metric versus CPU. Okay? If you if you look at CPU usage, you are typically, it's too laggy. K? Once once you see once the auto horizontal part of scaler see that stuff, you are you are already in trouble. Okay?
Dan Shappir [00:47:32]:
And with But it's not a metric that's built into node or whatever. There's no, like
James Snell [00:47:38]:
No. There is.
Matteo Collina [00:47:38]:
You can do.
Dan Shappir [00:47:39]:
There there's I there's
James Snell [00:47:40]:
an API for it. It. Yeah. Yeah. There's an API built into it, and directly in the note as part of the purpose API.
Matteo Collina [00:47:46]:
You need to enable it in prompt client.
Dan Shappir [00:47:49]:
Very cool. Very cool. We'll definitely look at it. Thank you for that. Anything else about pillar number 2? Okay then. Moving on to pillar number 3, news node LTS versions in production. I think it it even though people listening to us should be familiar with Node, I think it's worthwhile to mention what Node LTS versions actually mean.
James Snell [00:48:17]:
Mhmm. Yep. Long term support. This is basically Michael,
Matteo Collina [00:48:20]:
you want to take it?
Michael Dawson [00:48:22]:
Sure. Yeah. Like, long the you you can go to the the website. There are the on the GitHub. It's like no JS slash release. It'll have our our schedule. The you know, every every it's very predictable release schedule. We have a current, which happens every April October, and then every even current gets promoted to long term support.
Michael Dawson [00:48:44]:
Long term support means, I think, it's 30 months of support. So it lasts from, you know, October this year, for example, to April two and a half years from now. And the e so the odd currents, they only have 6 months of support. So, you know, why why we say you really wanna stick to the long term support versions is that, you know, that's the longest period of time that you can sort of be on a version that's not going to go out of service and back to AJ's point of, like, we don't wanna change things any anytime. We don't wanna change them because it costs us money. Right? So you wanna basically look at the release schedule and pick the LTS. It's gonna give you the longest runway, and, you know, I I'd also say, like, schedule. You don't have to move up to every LTS because we have multiple overlapping LTSs.
Michael Dawson [00:49:32]:
We either have, like, 2 or 3 usually going on at the same time. So if it was me, I would basically say, like, okay. When do I wanna go into production? Let's plan to have the closest LTS. And then, you know, 2 years later, I should plan on, like, okay. Now let's plan for upgrading that particular version to the next LTS. There are multiple phases in LTS as well. There's, like, an active phase where we we back port changes quite quickly. So if you wanna get new features, they still go into those LTS releases.
Michael Dawson [00:50:02]:
But about after the first, and I'm thinking it's 8 months ish now, I'd have to look exactly at the the numbers. It then splits into maintenance where things are more, like, as needed security security fixes, that kind
James Snell [00:50:15]:
of stuff.
Dan Shappir [00:50:17]:
Why do non LTS versions even exist, and why would I ever use one of them?
Michael Dawson [00:50:23]:
See, the there there are people who wanna be on the bleeding edge, and so those ones give you based on our our our schedule, we feed things into those non LTS versions first. So if you want to get the very latest greatest, you can try them out there. And we do appreciate that people test them out for us and give us feedback and you know? So if you wanna take advantage of a new feature, we we really do people want want people to try those out and give us that early feedback.
AJ O'Neil [00:50:51]:
And there have been cases where I've there have been cases where I've had to use a non LTS because there was a critical feature particularly related to web crypto or fetch or one of those standards that is cross platform standard for JavaScript that was only available at first in the in the non LTS. Right now, for example, Nodes ESM support has finally completed, but it won't be available until, what, v 24 without the the flag? So I I'll probably update to v
Michael Dawson [00:51:29]:
2020
Matteo Collina [00:51:30]:
Are you sure?
Dan Shappir [00:51:33]:
It'll be 23.
James Snell [00:51:33]:
Yeah. Are
Matteo Collina [00:51:34]:
you sure, AJ? Now I have I have a very good news for you. I have really very good news. We are likely thinking of back porting it to 22.
AJ O'Neil [00:51:46]:
Yeah. Oh, sweet. That's great. Yeah. That's that's that's amazing. Yeah. Because that that's something I have not been using ESM because, you know, like, why would I publish something to NPM that breaks everybody else's stuff and everybody else has to transpile, but then all those people are using bundlers anyway? Like, you know, ESM just didn't make any sense. And then when I saw that, I was like, yes.
AJ O'Neil [00:52:06]:
Finally, I get to to not have to screw around with all this, you know, window crap.
James Snell [00:52:13]:
This raises this raises the good point. It's like, why do we have this, you know, the schedule? You know, back if you think back to when before Node and Ios. Node was originally going way too slow. Ios came in and was going way too fast. So this LTS schedule was a you know, let's find a middle ground. Like, we're going to have 1 LTS per year, but why do 2 majors? And the reason for that is because the ecosystem needs to be able to have these features out at a faster rate than only one release per year. And so, you know, the the the short term, like, odd numbered, currents, those are primarily to help the developer ecosystem in Node, not the, like, enterprise, you know, production users. It's there to help, like, the the module developers in the ecosystem that that are producing all of these dependencies keep up on the rate of change and allows Node to be you know, to know, like, what's actually being used.
James Snell [00:53:10]:
How does this be evolved? You know? You know, might actually get used to these things before it goes LTS, before it goes where we have to maintain something long term.
Dan Shappir [00:53:18]:
And it's still considered to be a stable version, an official stable version, so I'm not, like Yep. Working on some beta or whatever. I am working on an official version. I just get the the, let's call it, modern or bloody bleeding edge features sooner, and I don't have to wait a full year Yes. For for that stuff. And I can have it ready in advance of that LTS release.
Michael Dawson [00:53:41]:
It still respects SemVer, so you you can you can expect that there shouldn't be really any breaking changes.
Dan Shappir [00:53:47]:
Mhmm.
Michael Dawson [00:53:47]:
But features go in more quickly. And it and it really does help us in terms of, like, the versions we promote to LTS. It's great to have that 6 months as a current because that really helps us find out, like, are there any things that we missed in terms of, like, did something was it more breaking than we expected? And, you know, means sort of that 6 months means that by the time we go to the LTS, we have a much better chance of it just being boring for everybody, which is what we like.
Dan Shappir [00:54:14]:
I really want to be respectful of all your time. We are nearing the time usually where we start pushing towards picks. I'd love to continue this conversation for now. It's also easier earlier for me because, we've switched to Daylight Savings and you guys well well, off of Daylight Savings and you guys are still, at least in the states, are still there. So I don't know how long you guys can go. Do we have another 30 something minutes, or do we need to start thinking about wrapping up?
Michael Dawson [00:54:47]:
I got time. Yeah. I'm all I'm okay.
Matteo Collina [00:54:50]:
I'm okay.
Dan Shappir [00:54:51]:
Okay. Let's keep on going at least for a while. Let's see how far we can push it. Anything else about this pillar before we go to the next one, which is a whopper? Okay then. So pillar number 4, it's automate testing, code review, and conformance as much as possible. Again, this is like a absolute truism of software development that has you know, it's true for a node, but it's practically true everywhere else in the world. By the way, there's this click, so I don't know where it's coming from. But, guys, please be aware that there's, like, this clicking sound going on.
Dan Shappir [00:55:33]:
Anyway, so what do we have to say about automating tests and code reviews and conformance that's node specific, or is it just, you know, do it?
Michael Dawson [00:55:48]:
I I think what my perspective on this would be is that, you know, one of the advantages why people we hear use Node. Js is that they can move really quickly and they can innovate quickly. For me, that's great if you can move quick quickly, but it makes your testing and your regression test all the more important. So while this is very important in most cases, it's even more important when you're moving fast. And because Node lets you move fast, that's why it's so relevant to you.
Dan Shappir [00:56:18]:
I I'm total I totally agree. Part of my job at almost everywhere that I've worked in the past over a decade, is going into existing projects and starting, you know, to mess with them and literally break them. And, like, the difference between between having tests and not having tests is like life and death, literally. It's it's like, am I how confident do I feel even going into this project?
Michael Dawson [00:56:48]:
Yeah. It's like if you can make if you can make a change, run the the test suite and feel pretty comfortable that it's not gonna the world's not gonna light on fire, that's what lets you move fast. Because if you don't, if you're like, oh, I made a change, but nothing's testing this, you're you're always very cautious, right, I think, and you're not gonna go as fast.
Dan Shappir [00:57:09]:
Now you did differentiate between, like, the 3 different kind of tests that people usually talk about, which is unit tests, integration tests, and end to end tests. Now I'm curious, like, because I I hear people different people putting different emphasis on different types of tests. So I I hardly ever encounter people who say, you know, you don't need tests, but I do encounter people who say, you know, it's all about the end to end tests. And other people are saying, no. It's all about the unit tests and and so forth. So I am curious where you guys which camp you guys fall in, if you even do fall in a camp.
James Snell [00:57:54]:
I for for me, I don't necessarily care about the type of test. I care I care about the test coverage. And I know a lot of people, you know, have a problem with chasing, like, you know, complete test coverage and stuff.
Dan Shappir [00:58:06]:
Or measuring test coverage.
James Snell [00:58:08]:
Right. I don't care necessarily what kind of test it is. I care about is this line of code tested. And too often, you know you know, folks will only test the happy path. You know, they'll only they'll write their test based on what they want the code to do, not based on what the code actually does, and they end up missing, like, you know, coverage on half the branches that that that their code, that their code takes or could take, and then they get it into production or make some kind of refactoring change and things just break.
Dan Shappir [00:58:42]:
My one of my problems with end to end tests, which on the face of on on on the face of it, end to end tests, like like, they have, like, they could have been the best tests because they literally test the system as it should work. But there are 2 from my perspective, there are 2 main issues with it. 1 is that they can run pretty long, which means that people run them less often. And the other problem is that, testing coverage with end to end tests or achieving good coverage with end to end tests can be pretty challenging.
James Snell [00:59:22]:
I I think Yeah. Because a lot of times
Michael Dawson [00:59:25]:
I was gonna say I think
Dan Shappir [00:59:26]:
I'd agree with kind of
Michael Dawson [00:59:27]:
the challenges. Like, the I think the end to end tests, like, along with that is it's sometimes harder to figure out what went wrong or, like, you made a tiny change and you only if if you only find that in your end to end test, it's probably gonna be hard to figure out what that tiny change is versus At
Dan Shappir [00:59:45]:
least you found it before production.
Michael Dawson [00:59:47]:
Yeah. No. No. So so so I think it's a balance between the 2. Right? Like, I think having unit tests, which gives you really good coverage of the very specific things, will help you find, like, hey. I just made a commit, and I broke something, like, on the you know? But broke something small, I can find that very easily. And so you want you want as much unit testing as you as you as you can afford to cover, you know, find those things, but then you still definitely need the end to end tests. But you probably don't need to test every single thing in the end to end test because, like you said, that quickly becomes too long, and, you know, you can't run it as often.
Michael Dawson [01:00:24]:
Right? So it's finding that right balance between, you know, having your unit test that can fill only they will be able to cover everything in the end to end style, but covering as much as you can and then as much of the the end to end testing is as practical so that it still gets run on a regular basis.
Dan Shappir [01:00:39]:
Also, it's much closer to the actual code, so you're much less likely to miss branches at least at the unit level.
James Snell [01:00:46]:
Right. And a lot of times, the integration tests, are incapable of of, testing particular branches, like, particularly if they're edge cases or, you know, should only happen in, like, critical failure situations where your end to end test isn't actually able to trigger those. Right? Because it's it's it's meant to be some internal failure or IO is failing in some case. Those units are going to actually make it make likely.
Dan Shappir [01:01:14]:
Yeah. We all know the remedy to a to a critical problem, which is console error.
James Snell [01:01:22]:
Mhmm. Of course. Yeah.
Dan Shappir [01:01:26]:
Okay. Anything else we want to say about tests? Any recommendations about the systems you guys use for testing? Any particular system or mechanism I should be using as a node developer?
James Snell [01:01:41]:
Use node tests. Use the the new test framework built into the runtime.
Matteo Collina [01:01:46]:
What I can tell is what not to use. Okay? Don't you jest. Make yourself a fan. No. This is true. Okay? If you're building a node system, jest has a lot of good features. If you're building, if you're using it for some of the, front end, meta frameworks. Okay? But, if you're building a node app, an API, or something like that, use, don't use it.
Matteo Collina [01:02:12]:
I I recommend because you cannot test a 100% of the branches with it, and, therefore, it completely defeat the purpose of of a testing framework. So if I can't
Dan Shappir [01:02:25]:
Why is that, by the way?
Matteo Collina [01:02:26]:
Because in monkey batch is global. So, if in the node, emits an error, you know, one of its own APIs, in the however, the error object did not create is different than the one that, Jess has put in the global. So if you do error, instance of error, it will turn false even though it's an error. You you don't know what Now now it
Dan Shappir [01:02:53]:
well, now we have, the the JS spec, we have error is error.
Matteo Collina [01:03:00]:
That's I
James Snell [01:03:01]:
mean, that that should that should help. But but, yeah, with with with Justin, you know, in the front desk, Jasmine, a couple others, you know, had this issue before where the test ends get the test you write ends up testing the mock rather than testing, you know, the actual run time, the actual code. We had this problem in workers. You know, for the longest time, we're doing local tests, you know, because our test framework originally, like that client side part, the original version of MiniFlare, was actually running a node. So when you would go to develop your your worker and test it, you were actually testing it against nodes implementation of something like readable stream, and then you actually go to run it in the run time and oops, it breaks because, you know, we have slight differences. You know, we're we're getting away from that now where you can actually test on the actual production code. But a lot of these test frameworks like just have that fundamental problem where you're not testing the thing you're actually running.
Michael Dawson [01:03:54]:
And I think Matteo's point might be, like, it it has some advantages if you're, you know, closer to the front end side of things. But if you're really just a a node microservice, you might be better served by something that's more node focused versus versus that.
Dan Shappir [01:04:09]:
And in that case, just use the built in node testing framework.
Matteo Collina [01:04:14]:
Yep.
Dan Shappir [01:04:16]:
Cool. Okay. Moving on to the next one. And I think you know what? We'll see if this is the last one, or we'll manage to get to number 6. It's kind of stopping in the middle if we if we stop in this one, and then we'll give us an incentive to do another episode. I would love to have you guys on again. This is such an awesome conversation. Okay then.
Dan Shappir [01:04:41]:
Number 5. And, again, this is just a golden rule in software development of but I think it has special meaning in the context of node, and that's avoid dependency creep. Can we explain what dependency creep means in general and what it means specifically in node?
Matteo Collina [01:05:03]:
So this is, probably one of the most misunderstood practice, especially, lately. It's, like, the node has been had had the success it had only because it was able to solve one specific problem. In fact, node didn't do it. Npm did. It it found a way to to do software reuse at massive scale. Okay? And by by in in what what's the mechanism? Well, by allowing more
Dan Shappir [01:05:39]:
And it turns out that your substantial portion of that reuse. Pretty much.
Michael Dawson [01:05:45]:
Alright. Is
Matteo Collina [01:05:46]:
it I don't know if it's a good thing or a bad thing. Okay? I am one of, like, I think, actually
Dan Shappir [01:05:52]:
You're that guy from the text you're the that guy from the xkcd strip about that,
Matteo Collina [01:05:59]:
Visibly, in the
Dan Shappir [01:06:00]:
Yeah. Visibly, he's about Italy. Yes.
Matteo Collina [01:06:04]:
So, the that's it. Okay? So it's, avoid dependency creep. So Node. Js had the massive success due to, this software use. It allows you to, for example, use different version of the same libraries in different, dependency trees of your app. K? This means that you can have, and this happens very often, readable stream 1 in your codebase, readable stream 2 in your codebase, readable stream 3 in your codebase, and readable stream 4. K? And when I will ship 5, you likely have 5 we'll have 5. Okay? That's what it is.
Matteo Collina [01:06:46]:
Okay? So there is there are some modules that get a lot of that are in a lot of dependency chain because typically for the typical historic reason. And at that point in time, it's, they were useful, but now probably way less so. So maybe you should stop using readable dash stream and maybe start using, you know, no no j the node just the node stream module because that's all of it. But, however, there's a lot of things where you still want to use that module, and therefore, here we are. Okay?
Dan Shappir [01:07:23]:
So so you made actually two points here, I think. First of all, you're saying node itself is advancing, and it's offering many built in features that in the past did not exist, that in the past we would have needed to bring in, like, 3rd party libraries. Now there are built in features in in the platform. And as with the browser, whenever I can leverage an existing part of the platform rather than bringing in a dependency, it's it's almost always a good idea. It's going to be a stable API, a well tested service API. It's gonna be there forever. I don't need to worry about maintainability, about security, about who gets ownership of it and starts pushing malware into it or or or whatever, and it's probably going to perform better and and so many advantages. So that's an obvious, thing.
Dan Shappir [01:08:22]:
But the other point you're saying is that I should be wary of having multiple versions of the same package running within my single node instance. Now I understand why it's a bad thing on the browser side because I've actually seen a browser based application deliver 3 different versions of Moment JS, which resulted in, like, a huge download, which is a problem on the client. Why is it a problem in my node server though?
Matteo Collina [01:08:58]:
The first problem is, related to your surface attack. Okay? The more dependency you have, the more you are exposed to potential attack. You want to have, genetically, the dependency that you need and only the dependency that you need in your tree. Okay? So this is the first point. Okay? Which, you know, each one is a vector is a potential attack vector. So you need to treat them like that. K? And the other stuff is it increases significantly the install time of the application. So if you do and increases, I don't know, CI time.
Matteo Collina [01:09:36]:
K? Just a tiny bit. K? But then another app can have easily 3, 4000 dependencies once all said and done. And then you start seeing, oh, okay. Can I just maybe remove a 1,000 of those? K? Each one of them needs to be downloaded in in the Just
Dan Shappir [01:09:55]:
a 1,000.
Matteo Collina [01:09:56]:
You know? I'm just, like, a lot of them like, there are some of them that are trivial. Okay? And, frankly, they should, you know, not be mobilized, but there we are. And some of them, they are
James Snell [01:10:11]:
need to be down leveled. Right? I mean, they just people just don't update their dependencies when they can, and so some of them end up just being brought in just because somebody decided not to update.
Dan Shappir [01:10:25]:
It's it's also the fact that it's like it's like like this sort of a skeleton. Like, the hip bone like, how that song go? The hip bone's connected to the thigh bone and so forth. So you bring in one note package, and that brings in 2 more, which bring in 8 more, which bring in 16 more. And and all of a sudden, you have, like, the entire universe downloaded into your, node instance, and you you did put that comic strip in your article about how the NPM modules folder is heavier than a black hole. How how do how do I contend with that? You know, if
Michael Dawson [01:11:03]:
I I I think the principle was about, like, be more intentional about that. If you're gonna you can easily pull in a packet and you're using some small part of that package And but take you should take a look at, like, what all did that pull in? If that pulled in a 100 other packages and you've effectively replaced 10 lines of code that you might have written yourself, maybe you should just put the 10 lines of code in. Right? So, you know, as Matteo said, the reuse is one of the fast, fantastic things about the the ecosystem. It's really easy to pull in code and reuse it. That's great. But I think we could use a little bit of a shift towards being a little bit more intentional in in looking at what you're pulling in versus the benefit you get, so that you're you're sort of doing the right balance between, hey. I'm reusing code easily versus the sort of risk that I'm taking on because, you know, I've got a huge amount of code. It's not just the attack factor.
Michael Dawson [01:11:59]:
What if there's a bug you wanna have fixed? You know, are you able to do that yourself? If not, that's something you should probably at least think a little bit about.
Dan Shappir [01:12:09]:
Yeah. Maybe you don't actually need left pad.
Michael Dawson [01:12:13]:
Right. Like yeah. You know?
Dan Shappir [01:12:17]:
Yeah. The the the sad thing is that, given the average, experience of developers, there's a good chance that half our listeners don't even get that joke about left pad because they came into the industry after it happened. Yeah.
AJ O'Neil [01:12:33]:
Well, the question is, are they still using it today?
Dan Shappir [01:12:36]:
There's a good chance that they are, though, but they probably don't know it because they're probably you not using it directly. They're probably using something that uses something which uses left bad.
AJ O'Neil [01:12:46]:
I think we need an ethos change to be more like Go and Zig and other sane languages. Make the standard library great again, And get rid of all the crap dependencies that I mean, there's so many, even security, dependencies where the people who are doing it obviously don't know what they're doing. You can't blame them because no one who did know what they were doing was doing it. Right? But I remember one of the early, very, very popular OTP libraries was, atrocious. You know, like, there's there's there in in our industry, I think because of there being so much money available, and thank goodness there isn't now, I actually think I I hope that the interest rates stay high. I hope they don't go down for the sake of our industry. For the sake of, you know, lots of other things, maybe. I don't know.
AJ O'Neil [01:13:37]:
But our industry was ruined by low interest rates. Because with free money, there was no responsibility to a customer, and then there was no there was no craftsmanship. And and then it became it became an ego thing. Like, look. I don't know what I'm doing, and I'm getting so much done anyway. Look. I don't understand how this framework works. I don't understand how the library works, but look how great I am anyway.
AJ O'Neil [01:14:04]:
And we need some sort of an ethos change to, like, hey. I'm able to do this with just a standard library. Isn't that pretty cool? Hey. I I'm able to understand how my code works. Hey. I I've got a handle on what my application is doing. Because if we don't have that ethos shift, then we're we're gonna get stuck in this the same rut that we're in. I mean, like, we're not gonna leave the rut.
AJ O'Neil [01:14:25]:
We're already stuck in the rut. We're not gonna get out of it.
Michael Dawson [01:14:28]:
No.
Dan Shappir [01:14:28]:
So an interesting thing that I have to mention. So a few episodes back, we've had we had Ryan, Dahl as a guest to talk about the dino 2 when it came out. Now interestingly, when dino itself first came out, dino 1, one of the things about it was that they avoided NPM and did try to provide, like, their own more significant built in standard library. And the thing about d n o 2 is that they well, surprise, surprise, they now support NPM because it turns out that without supporting NPM, you can't really
AJ O'Neil [01:15:03]:
get enough investment.
Dan Shappir [01:15:04]:
Well, not that. You can't really build practical things, especially for the enterprise.
James Snell [01:15:09]:
Users want you just wanna use users want to reuse NPM modules. I mean, that's all it is. I mean, so that that that that the whole joke about NPM being this black hole, that's exactly it. It's got such a massive gravity in the ecosystem that you cannot avoid it. Right? And and
AJ O'Neil [01:15:26]:
Right. But I don't I don't say I'm not gonna go use go because I don't have NPM, or I'm not gonna use Rust because I don't have NPM. Right? I mean, when you create something new, when you create something that's fundamentally different, you have the liberty to not take the baggage, you know, from from prior years. Like, you don't you don't use c and and well, in in some rare cases, you use c and go, like SQLite or something like that.
Matteo Collina [01:15:51]:
But, you
AJ O'Neil [01:15:51]:
know, in other languages, they're not they're not afraid to say, hey. One of the reasons we're creating a new language and a new platform is because we want to leave the crap behind. We don't want the crap to come with us. I'm not convinced. Sad that Dino conceded on that point.
Michael Dawson [01:16:05]:
I'm not convinced the other languages have have totally have necessarily done better. They may be in a different point on their journey. Like, I know in Go, I'm I'm I'm working on build packs for Node. Js. They're written in Go. That's the place we actually have, like, a dependencies that's deleted that's preventing things from being updated. And so, like, you know, NPM has gone through a fairly long learning process, and some of these other languages, like, it'll be interesting to see if they end up in the same place or, you know, they just haven't hit some of the challenges that you get with the scale that notice gotten to you yet.
Dan Shappir [01:16:42]:
I'm trying to remember who said it. It might have been c o. I don't re I don't remember. But, basically, they said that without NPM, we wouldn't have had caught. So so even even though even though NPM is not perfect, it's the most used, and that definitely says something.
AJ O'Neil [01:17:04]:
Yes. Though I am sad for for Metaverse. I am sad that they based cargo around NPM because it shows, and it's got a lot of the same problems. Whereas the Go package manager is empirically as perfect as it can be, meaning that it has the fewest trade offs. And you can prove that mathematically looking at the graphs, and there's a path where that's been done. So that that is really sad that we actually have something that we know both mathematically and practically works out, and we still choose other things.
Matteo Collina [01:17:32]:
Well, they was not there. Like, the go back
AJ O'Neil [01:17:35]:
to management I know. Yeah. For MPM, I know. But I'm saying cargo. But, like, it's it's sad that the I don't think it was
Matteo Collina [01:17:42]:
not there. Sorry. It was not there. I think it cargo predates the go back to manager.
AJ O'Neil [01:17:46]:
I'm pretty sure.
Dan Shappir [01:17:47]:
Yeah. Yeah.
Matteo Collina [01:17:48]:
Alright. I I guess came out very, very, very late in the game. For a long time, go was, in fact, the original d n o one, package package management, we came out from dino from Go. And they just say, well, you point us you point it to a URL and then you download it and they it it handle it. It handles it. Okay? Which is what's essentially our dependency we're managing Go, prior to that.
AJ O'Neil [01:18:20]:
Okay. Or, yeah. Yeah. Yeah. For the mono repos. Yeah. That that that is definitely yeah. Okay.
AJ O'Neil [01:18:25]:
I see what you said. Yeah. Because the it came out in 2018, and then it was and it was confirmed final in 2019, which it seems that's more recent than what it seems like. It seems like it was a longer time ago, but then, I guess, Rust wasn't really even hitting popularity until after 2018. So when I think about it, I I my memory is wrong. My memory is corrupt. I'm faulty. My bad.
Matteo Collina [01:18:51]:
But, yeah, I mean, you know, going back to
James Snell [01:18:53]:
some of, you know, the kind of the original thing with dependency creep and everything else. So, npm, like I said, it has this massive gravity, and if folks are using those modules, they want to keep using them. Unfortunately, there's just so many modules on there that they don't need to use. My my economical example, if you go out there and I and I don't wanna, like, pick on it too much, but there's a module out there called is even. All it does But
AJ O'Neil [01:19:17]:
that's that's parity.
James Snell [01:19:18]:
That's a joke. It it doesn't matter. I've seen people use it. It doesn't matter if it's a joke because peep I've actually seen people use this in their code.
AJ O'Neil [01:19:27]:
Like, not not a joke? They Yes. They used it as not a joke.
James Snell [01:19:32]:
Yes. Like because it was there.
AJ O'Neil [01:19:36]:
That's scary.
James Snell [01:19:37]:
It it is scary. But I I you know, my the first time I I found the isn't even module, which all it does is to is, pull in the is odd module and and negate it.
AJ O'Neil [01:19:50]:
And that that, like, has a list of a million numbers. Right? Or something like that? It's it's not even something simple like doing mod? No. No. Because I know one of the parity modules just has a list of numbers, like, 1 to a1000000, and then for every other one returns true? Okay. So it's not that bad.
James Snell [01:20:08]:
No. This actually does work. You know? And and and we'll check to see if the the data of the input is a number and, you know, and and that kind of thing that is odd. But all is even does is pull that in and negate it. I've seen you know, there there are a ton of modules on NPM that, like, you just don't need, and people pull them in anyway because they're not thinking about it. They're not being intentional about it, going back to Michael's earlier point, Or they don't understand what the module is actually doing. Right? And that's what they need to be focusing on. Goes back to same thing with with problem.
James Snell [01:20:43]:
I have a problem with about what you're doing.
Dan Shappir [01:20:45]:
I have a problem with that statement because to a great extent, the whole idea if of reuse is that I don't need to think about the implementation details. I can basically just look at the API surface and be content with that. If I assume if I can assume, let's call it, a good a good actor. If if I'm starting if I'm if I need to start looking under the hood of every NPM module that I'm using, why am I even using these modules?
James Snell [01:21:25]:
It comes back to the, you know, being intentional about it. Right? And I to some extent, yeah. But you have to understand there's a trade off. If you don't understand, you know, what the module is doing, it might be doing something incredibly, you know, performance, you know, costly. And yet and suddenly your application is slowing down. You go into production. Why is it slowing down? Well, when, you know, Matteo and I, countless, countless of consulting, jobs, we went out and found, hey. It's your dependencies that are slowing you down because they're just not, you know, written to be, very, performant in any way.
James Snell [01:21:59]:
And folks, well, we didn't know that. If we had known that, we wouldn't have used it. Well, you know, do some digging. You know, look at what your dependencies are doing. You know, it it you have to be aware of the COVID-nineteen pandemic.
AJ O'Neil [01:22:15]:
A good metric. Because I I think that with rails and I don't think that this necessarily was what the rails community intended, but it, bad pun. You know, the idea went off the rails. The dry. Right? Don't repeat yourself became it became a sacred cow that people didn't understand, and they just started to say it without knowing what they were saying or what it was supposed to mean. And this don't repeat yourself became this, you know, this this religious, fervor. And I I think a good metric would be would does the number of letters you have to type to search for it or or or query for it exceed the number of characters you would have to type in order to implement it? Because if so, you're on the wrong track. You should just copy and paste that code or type it out again.
Dan Shappir [01:23:11]:
It'll be interesting to see if, AI code generators make a dent in this. If people can instead of pulling an and and if they actually make an improvement also, if somebody instead of, pulling in a module that's does something can still, like, chat GPT or Copilot or whatever, write me code that does that thing and then copy paste it into into their code. Is that better or worse?
AJ O'Neil [01:23:39]:
I have had great success with ChatGPT writing far better code than what exists in the ecosystem that I could find. And I'm not just looking at modules that have the 1500 plus stars. I'll look for things that have 10 or no stars. I'm just looking for the best code that's available, and I'll go peek at the source code. 22 things that come to mind. 1 was shot 256. There because web crypto has shot 256, but it's really, really slow because of the context switches and the async. So if you need shot 256 for anything more than a one off, I would not recommend using web crypto.
AJ O'Neil [01:24:16]:
So all these modules on npm that have shot 256, they're all really legacy. They're you know, some of them are using a transpiled buffer implementation from Node. Like, none of them are using u
Matteo Collina [01:24:27]:
n
AJ O'Neil [01:24:27]:
8 array and modern JavaScript. They're all, like, decrepitly old. And I asked GPT to write me from scratch a SHA 256, and I was so skeptical. I spent 2 hours testing it, pulling from other libraries, like, grabbing their tests and bringing that in. Because I thought there's no way that it that it created a better library than anything that exists on npm in a in a one shot. But it is a really well known algorithm. There's lots of training data and lots of languages, and GPT does kind of tend towards simplicity. It doesn't have a context window to be able to create 7 different class hierarchies to do something.
AJ O'Neil [01:25:05]:
It kinda has to be able to do it in a function or 2, which I think, you know, also speaks to the the greater average of the human consciousness. Humans are not really good at holding 7 different class hierarchies in their context windows. Although, they they like to think that they do. But in some ways, I think that GPT is more truthfully reflecting reality than people are perceiving it. Another instance was a CBOR parser. And, you know, CBOR is something there's not very many implementations of it. But the implementations that exist, outside of JavaScript are extremely high quality. And so it was able to write me a CBOR parser in a one shot other than I had to make a a follow-up prompt because there was one function that didn't fit in it I guess, didn't fit in its context window.
AJ O'Neil [01:25:54]:
So I had this I could tell that it didn't have, one of the functions was missing. And so I said, hey. You're missing this. And I took that, and it worked. And so it at least in JavaScript, I can tell that and and part of it has to do with my memories because in GPT, I've told it, hey. Remember that I prefer this style. Remember that I prefer this style. So I I have also prompted it to to be simpler in the way that it writes code.
AJ O'Neil [01:26:20]:
But it was able to one shot 2 complex things that, you know, certainly nobody could write in 30 seconds. And very few people could write and feel confident that they wrote it correctly. And, you know, I was able to test it and and see that it did work. So but I think it takes the senior mindset to do that in the first place because you have to be looking for, hey. I looked at the code of this shot 256 implementation on npm, and it's absolute garbage. Not necessarily because it was always garbage, but be but but sometimes just because, like, it's got browserified translations, which, hey. Back in, you know, 2010, that's that was what you had to do.
Dan Shappir [01:26:59]:
That was I don't think it's the senior mindset. I'm looking at my kids, and, you know, they're getting into dev, and they make significant use of those AI tools. So I definitely think that there's a possibility that AI tools may reduce the amount of packages that we import because they'll they'll write those one shot type codes for us that that we often need instead of, you know, importing a
Matteo Collina [01:27:27]:
And then what will happen is that a box will spread everywhere.
AJ O'Neil [01:27:34]:
Yeah. That's the thing. It's that's why I said it takes the senior mindset because you have to know to test it. You have to know to determine if it's slop or if it's real. Because depending on the day, you know, when they update to a new model or, you know, do the revisions, I'll I'll have a day where I'm coding with GPT 4.0, and, you know, it's just like banger after banger. And I'm like, wow. And then a day or 2 later, I'll be asking it questions that might even be simpler or whatever, and it'll turn out just absolute crap. And it's like, okay.
AJ O'Neil [01:28:02]:
I gotta write this myself.
Michael Dawson [01:28:05]:
I I think that that's actually another aspect of of the reuse is that, like, if you're if you're your own person, like, if I'm just writing code for myself, I don't mind writing some new stuff and using that because, like, I'm the one who's gonna have to maintain it. If you're working in a company, I don't really you know, if I ran a a large company, I wouldn't want a 100 copies of the same thing written by 10 different people even if they're using AI to do it more quickly because there's gonna be different bugs, there's gonna be more investigation. So part of the the sort of the reuse is being intentional about what we what you reuse. And when you do reuse things, like, the great thing in the JavaScript ecosystem is we have tons of choice. The challenge is that we have tons of choice. So at least, like, within an organization, you should try and rein in that choice a little bit and say, well, okay. We're gonna use one version of x. Like, let's not pick 10 different ones because now we've just increased our surface area and our risks by 10 times.
Michael Dawson [01:29:03]:
We're gonna pick 1. We're gonna reuse it. And, you know, that's one way of continuing to maximize the value you get through use, but, you know, being intentional about the dependencies you have in your application. And as an organization, managing the risk so that you get a good balance between benefits or reuse versus the code you've got in your code base?
James Snell [01:29:24]:
If we bring it if we bring it back to the pillars, you know, if you look at every single one of those pillars, a key ingredient in every single one of those is intentionality. Right? It's, you know, get you to stop and think about your code, in some aspect of it. You know, what are you testing? What dependencies are you using? Right? How are your tasks broken down? Right? All of it is just about this this notion of being very, very intentional about what you're doing with your application. Dependencies are no different. Don't just pick a dependency because it exists. Pick a dependency because it does what you need it to do the way you need it to do it. Right? And and you know and understand what it's doing. Yeah.
James Snell [01:30:07]:
And it and it doesn't matter. If you're having AI write your code, it's the same thing. Right? You have to be very intentional about it, about about what you're trying to accomplish.
Matteo Collina [01:30:16]:
Guys, I need to drop. Unfortunately, it's about time for me. So I just want to say thank you very much for for joining. I for time, I would stay longer, but at this point, I really need to drop.
Dan Shappir [01:30:28]:
Okay? Thank you very much for coming on. We will I you're going to be a guest on our show to talk about something else in any event pretty soon, so we'll see you then. So thank you on thank you very much for coming on today. And I'm going to push us the rest of us into PIX anyway. We will just have to bring you invite you over to talk more about the pillars because we literally made it halfway. We made it into the middle of pillar number 5. So now we have the rest of pillar number 5 and then 6 through 9, and this is such a great conversation. I'm I'm so happy that it's turning out this way.
Dan Shappir [01:31:02]:
So thank you, Matteo, and, and see you in a bit in, like, a few more in a few weeks.
Matteo Collina [01:31:09]:
Bye. Bye. Bye. Bye.
James Snell [01:31:10]:
Same with you. Bye.
Dan Shappir [01:31:15]:
And you guys so, again, I'm gonna push us to PIX. AJ, do you wanna go first?
AJ O'Neil [01:31:22]:
Sure. I've got a couple. So I'll go ahead and throw out my link to the SHA 256 implementation. If you have an application where you need to be doing multiple shaas in a row, this this is the best implementation that exists in JavaScript. At least, there might be one that's just as good, but I was not able to find it. So I had to to publish this. This the and and it has been tested, extensively. So I, I am very, you know, I I dollars are on the line with it.
AJ O'Neil [01:32:00]:
But, anyway, so I'll I'll do that just as a a self promo since I since I talked about it. Because yeah. If web crypto works, because you only need to do 1 or 2, that's great. But the other the legacy modules that are out there, I just I would not recommend them because they're they're doing all this weird Browserify stuff or, like yeah. It's just they're just they're old. They're old. They're dated. They need to be replaced.
AJ O'Neil [01:32:24]:
And, Yeah. So go put the first star on there if you want to. And then I another thing I'm gonna pick, we're heading into winter. So we're we're in this season right here where I am of of nearly perfect temperature, which, the the weather's been really odd this year, and the the cycle of it's been kinda strange. But the last week or 2 has been pretty perfect temperature. We're heading into the thirties this week. So, it it it's and below freezing even. So that's that as soon as it came, it's over.
AJ O'Neil [01:32:58]:
That's that's how Utah is. It's like your spring and your fall are very, very narrow bands. Like, even 2 weeks ago, it was up in the eighties. This week, it's down in the thirties. So that's how it goes. But with it becoming winter, static shock is a thing. At least for us here in this dry climate. And a buddy of mine introduced me to these grounding mats, and they sell them as kind of woo woo, hocus pocus, like, it's gonna alleviate your back play pain problems while you sleep or cure your depression, which I don't believe that a grounding mat is gonna do any of that.
AJ O'Neil [01:33:36]:
If you do believe that, I'd be curious to know why. But I and, honestly, I I actually would be curious to know why if there's is there some sort of science behind it or some sort of, like, actual, what what it what it lived experiences or whatever. But but I get I got them. And I've got one for my feet and one for my hands Just because I I started to develop this fear of, like, touching the keyboard. Because every time I did I mean, it was it was a heavy shock. It wasn't just like a little, like, oh, I you know, I touched your sweater. It would really build up. And so I got these grounding mats so that I don't shock things.
AJ O'Neil [01:34:15]:
Also, real story about electric shock. I took my home network down, for 2 days. And I kept on unplugging things and replugging them, and then it would work for another hour, and it would go down again. It turned out there was a network switch that was connected to my desk. And I believe that what had happened was that I had inadvertently touched the one of the cables that went to the network switch. It had gotten into a bad state where it was just spitting out some sort of packet. I I I honestly believe it was from static shock. Because I had unplugged a bunch of other things, but I'd missed that one switch.
AJ O'Neil [01:34:56]:
And when I finally found that that, oh, I I haven't actually power cycled this thing like I thought I had. I think I had power cycled it, but it had a USB connection. So it would still add power, like, re from the USB or or something like that. But, anyway, I unplugged it, replugged it, and then I didn't have those network problems anymore. Very, very weird situation. But I think just getting shocked flipped a bit. So it also could potentially protect your, your electronics from malfunction having one of these, grounding pads. So I linked to one that actually feels nice.
AJ O'Neil [01:35:30]:
It doesn't it doesn't feel cheap and junky. It it has, it it feels like real leather. I don't know if it is, but it it feels like real leather. And it's very, very effective in terms of, if I'm using it, I'm not constantly shocking everything on my desk. If I'm not using it or I walk away on the other side of the room and come back, then I, you know, I put my hand down, and, of course, I shock myself. Anyway, grounding mats. Who knew? Who knew that could be a pick? But it is. And, that's that's what I got for y'all today.
Dan Shappir [01:36:03]:
Excellent. So now I'll go with my picks. I actually have 2 picks. So the my first pick is we watched on Netflix the, limited series called monsters, the Lyle and Eric Menendez story. This is a pretty famous and pretty gruesome story from, the end of the eighties. I think it happened. The actual event happened in 1981 about these 2 brothers that basically executed their parents, and, they were caught. They went on they went to a trial.
Dan Shappir [01:36:35]:
I won't spoil the rest of the story. There's actually three way the funny thing is that there are actually three ways to watch it on Netflix. There's the, limited series, which is a dramatization of the story. There's, a documentary series, and then there's a documentary movie. We watched the series and enjoyed it very much, and that's the thing that I would recommend the most. It's well played, well written. It's it's just it's just good pretty good television. Afterwards, we tried to watch a documentary series because we were kind of interested in the story, but it I don't know.
Dan Shappir [01:37:19]:
It just went into way too many details for us. So instead, we watched the documentary movie, which was interesting in the context of the series we just watched. But, again, if you're gonna watch something and just the one thing, do just watch the, limited series. Again, it's called Monsters, the Lyle and Eric Mineta story, and it's it's, it's a pretty good story. The one thing interesting about it is that recently, I think the governor of California, I believe, said that he's reviewing their sentences because and people are saying that it's potentially because of the stories that came out due to these, all these shows and all the discussion about them, which is kind of interesting how art impacts life, I I guess, in a sense. Anyway, so that's my first pick. My second pick is, things have been it's kind of people have stopped talking about it maybe because of the elections in the US or maybe people just moved on, but there was a whole lot of craziness around WordPress. Like, it kinda seemed like, the guy who's running automatic, who is like the, what's it called what's it called, the benevolent dictator of WordPress, which is Matt Mullenweg, I think his name is pronounced, seemed to kind of went off the rails.
Dan Shappir [01:38:42]:
I won't go into the entire story. It's it's pretty out there. Lot of crazy things happened. And if you are curious about what actually went down and and what's potentially still going on, the one video that I would recommend to learn everything about it, at least everything as was, as of about 2 weeks ago, is a a video made by, Theo, also known as Theo 3gg. It's actually in his Throwaways channel. We'll post a link. He actually spoke with Dan Saltman, another podcaster streamer, a bit less technical, and explained to him his the whole thing. And Theo was kind of involved in it because he actually spoke and interviewed Matt, and in and to the extent that his videos became part of the depositions in the ongoing lawsuit that's related to this whole story.
Dan Shappir [01:39:44]:
So, again, if you're interested in this craziness and wackiness in the open source world and where open source can go in bad situations, then it's a pretty interesting video to watch, and I and I recommend watching it. So these are my 2 picks for today, and I'll and I'll post the link to the links to both of them. How about you, James? Do you have any picks for us?
Matteo Collina [01:40:12]:
Let's see. Well, first
James Snell [01:40:13]:
of all, I'm I'm sorry if I get any audio. My earbuds just died, so I'm on laptop speakers now. So there might be some echo. So I apologize for that. Let's see. Fix for for today. Next week, we got NodeConf EU happening in in Ireland. It's always my favorite time of the year getting back, getting back to Ireland.
James Snell [01:40:36]:
We're actually returning to Waterford Castle. It's a the the conference is an actual castle. You know? It's just an absolute wonder fantastic, venue. There's still some tickets available. It you know, I know folks from the US. It's maybe a little little harder to get over there, that you know, last minute, but if you're over there in Europe and you have the time available, it's absolutely fantastic conference. Gonna be talking about, cross run time compatibility. So all this effort, like, Deno to act like Node.
James Snell [01:41:10]:
Bun working back like Node. Workers is trying to act like Node. How do we ensure that the all these different run times work the same when it comes to, like, you know, standard web APIs, that kind of thing? So we're gonna be talking through a lot of the challenges that, that all these different run times have, to actually make sure that they're compatible, with a language like JavaScript that allows you to basically do whatever you want. So that'll be that'll be a fun talk. But the other other side of it, and this is just my personal side, my son is going, my son has has been a contributor to Node for a couple of years. He's doing his own talk there with, with with another person, Claudio. And we're talking about the work that they've been doing to improve Node, release downloads based on Cloudflare r 2, and some of the other some of the other work that they've been they've been working on. So, if you have time, go.
James Snell [01:42:01]:
We'd love to to to to meet folks there, and that's
Dan Shappir [01:42:05]:
The family that notes together stays together.
Michael Dawson [01:42:09]:
Oh, yeah.
Dan Shappir [01:42:11]:
Cool. And how about you, Michael?
Michael Dawson [01:42:13]:
Yeah. I'll I'll my first one, I'll just agree with James. No cuff you next week is gonna be fantastic. The other thing I've been doing lately is spending time, like, learning a little bit more about AI, trying to use the libraries from JavaScript. And the the great thing is often, like, JavaScript or TypeScript is the second language supported. So if you look at a LAMA, a Lamedx, Langchain, which are all leading libraries in in the AI space, They they obviously all start with Python because really data science came out of that that sort of space, and that's the language they use. But most of the the leading libraries also then support TypeScript as their second language. And I think that that shows a recognition of the AI ecosystem that, like, JavaScript and TypeScript is gonna be an important player in terms of consuming those services.
Michael Dawson [01:42:59]:
In terms of my pick, I've been looking at this week, it's the b agent framework. It's actually one which started life as TypeScript instead of Python, which is nice to see as a node developer that somebody started with a a JavaScript implementation. It lets you write agents that call functions, more easily. So I've been playing around with that. And if you're interested in, you know, node and and consuming AI from JavaScript, TypeScript, I I throw that over as my pick to go take a look at that.
Dan Shappir [01:43:28]:
Very cool. Now before we wrap up, if people want to get in touch with you guys to talk about what we talked about today, I don't know if you still do consulting work or in general just to speak with you. How do they get in touch, Michael? What's the best way to contact you?
Michael Dawson [01:43:42]:
I think, you know, Twitter, my handle's there, mhthawsonone. You can just reach out to me through that.
Dan Shappir [01:43:48]:
Excellent. And how about you, James?
James Snell [01:43:50]:
Same, on Twitter. I'm j a Snell, on Twitter and on GitHub. I I think we have to be following each other for you to DM, DM me, but, you know, feel free to reach out. Do a public chat out on me on on our happy chat.
Dan Shappir [01:44:07]:
Excellent. So, guys, it's it was great having you on, and I'm I really hope we can organize and schedule the follow-up because we do really need to cover the rest of the pillars. The ones that we did were so great. Thank you for coming on. And to all our listeners, thank you for listening in, and goodbye.
Hello, everybody, and welcome to a super exciting episode of JavaScript Jabber. Today on our panel, we have Ajay O'Neil.
AJ O'Neil [00:00:14]:
Yo. Yo. Yo. Coming at you live, healthy, and well from the perfect temperature in the shed. It's been a while.
Dan Shappir [00:00:23]:
And me, I'm your host today, Dan Shapiro from Tel Aviv in Israel. And today, our guests are Matteo Collina. Hi, Matteo.
Matteo Collina [00:00:32]:
Hello. Hi, everyone.
Dan Shappir [00:00:34]:
James Snell. Hi, James. Hello. Hello. And Michael Dawson. Hi, Michael.
Michael Dawson [00:00:40]:
Hi. How are you doing?
Dan Shappir [00:00:42]:
And today, we brought you all over to talk about this excellent article post, you know, that you've written. I loved it very much to the extent that as soon as I saw it, I contacted Matteo and told him, you have to come on our show to talk about this. All you guys out there should also read it regardless of what we talk about it here, and it's called the 9 node pillars. Nine principles for doing Node. Js right in enterprise environments. As I said, this is an awesome article. Who wants to start talking about it?
James Snell [00:01:17]:
So just go read it. I mean, none of those. Yeah. So
Matteo Collina [00:01:20]:
Okay. Let me start. This article starts from an idea of from start from experience. Okay? Start from at the key, the experience of, you know, developers do Node JS all the time. They think they know Node JS, and they don't know know Node JS.
Dan Shappir [00:01:43]:
Okay? That's a pretty unfortunate statement.
Matteo Collina [00:01:46]:
It's No. It's true.
James Snell [00:01:47]:
It's true. It's absolutely true. You know, we Matteo and I, you know, when we the both of our previous employment, we were working doing a lot of consulting work, going out with customers and seeing the same problems over and over and over again. And in every single case, it always came down to folks not really understanding how node worked internally. Like like, you know, what what at you know, how does the event loop work? Those and I things. And
Dan Shappir [00:02:13]:
It just occurred to me that I skipped a very important, point while starting this conversation, and that's, like, who you guys are and why it is that you guys actually do know so much about how node works and how it should be used. So maybe you should you guys should do a brief introduction of yourselves.
James Snell [00:02:36]:
Yeah. Yeah. We can do that. I'm gonna go first and then let
Dan Shappir [00:02:40]:
let you
James Snell [00:02:40]:
guys go go next here. So, James, now I've been you know, I'm currently with Cloudflare. I work on the the the workers' runtime, but, you know, a lot longer than that, I've been involved with Node. Coming up almost on 10 years, involved with Node. And, the at the end of this year, it'll be exactly 10 years. You know, prior to my current employer, you know, you know, Mateo and I were doing all kinds of consulting work, around Node, use of Node, how to do things correctly, help people with performance, performance problems there, having that kind of thing. But, also, just they've been contributing a lot to node. So a lot of the things like the URL, Yeah.
James Snell [00:03:24]:
The original URL parser, not the original one, the
Matteo Collina [00:03:27]:
the the
James Snell [00:03:27]:
web w g, and
Matteo Collina [00:03:29]:
h p two and a bunch
James Snell [00:03:30]:
of other things, that I've been involved with with with adding. So that's me. That's my background.
Dan Shappir [00:03:34]:
Parsing URLs. That must be so easy.
James Snell [00:03:38]:
No. You you can I recommend for for a future episode, get, Yaghi san here? He did the the the ADA URL implementation that Node now uses, and he can tell you why it's not easy at all. So
Dan Shappir [00:03:52]:
Yeah. I know. I was just being facetious.
Michael Dawson [00:03:55]:
Yeah. I'm Michael Dawson. I'm the Node. Js lead for Red Hat and IBM, and I got, you know I've I've I actually got involved in the project around the same time that James has. And so I've been working for a very long time, in the project, a member of the technical steering committee, working a whole bunch of the different, working groups. Particular, like, node add on API is one of the ones that I'm I'm pretty active in in the build working group. And I think back to your earlier question is, like, I think that the challenge is is that you can very easily get get started with Node. Js, but actually getting it right is a little bit more difficult.
Michael Dawson [00:04:31]:
And that's why we we, you know, we see things like some specific guidance can really help people going forward. Over to Matteo.
Matteo Collina [00:04:38]:
So hi. Hi, folks. I am a little bit under the weather today, so I'm sorry. I didn't want to to to defer the the recording. So so sorry if I'm less, I don't know, excited as usual.
Dan Shappir [00:04:53]:
Very well.
Matteo Collina [00:04:54]:
It's, look. Well, I, well, I have I have a at this point, I've been doing doing Node. Js for a long time. I have accumulated, a few 100, NPM deploy a few 100, modules on NPM, which more or less total, a very nice 1%, close to 1% of the total number of down of downloads of MPM itself. Wow. It's it's a little bit unbelievable, to be honest. The numbers are, you know, it has way too many zeros in them. Okay?
Dan Shappir [00:05:31]:
You've been busy.
Matteo Collina [00:05:33]:
Me. Well, yeah. Everybody seems to love the the code that I push that they push out for free. So, anyway, few years back, I started this company called Platformatic to, you know, to push Node to the next level. And that's where what we are trying to do. And, and we have been trying to fund some of those initiatives and things and promote, Node. Js. So here we are.
Dan Shappir [00:06:06]:
Cool. Now you guys all work at different companies. So you're obviously all 3 of you very much involved in Node, but your day job is at different places. How did it happen that all of the 3 of you came together to write this article?
Matteo Collina [00:06:22]:
Oh, I can take this. So, basically, it's actually one person that is missing in this call, which is Natalia that was also part of the review. Okay? And Natalia is also the lead owner and for JavaScript, DX and DevTools for Azure. And the 4 of us like, this started from my ID for from, an idea that I had a few months back and says, look. How come we can how can we promote and solidify that knowledge? Okay? And how can we, stop start pushing back against the, all the bad tutorials, all the bad all the bad practices that are out there and plugging every single Node. Js code base that I have that I have seen. K? Because it that's that's frankly what it is. So, at that time, I started looking and said that I pinged a few friends and decided, look.
Matteo Collina [00:07:20]:
Who can who can I ask? I want representation for a bunch of different companies and so on. So and let's try to put the our our minds together and write something up that can be, that, you know, we can be happy with and can help developers, you know, you're doing Node. Js well and stop those, you know, spaghetti's code mess that they do most of the time.
Dan Shappir [00:07:53]:
So
James Snell [00:07:53]:
Yeah. And one one important point for me is, like, none of none of the information in this blog post is new. It's stuff that we've talked about in in talks over the years for conferences and workshops, and,
Matteo Collina [00:08:05]:
you know, each of us in in
James Snell [00:08:06]:
in various ways have have talked about these things before. Unfortunately, a lot of that gets kinda washed out in the noise of, like, you know, there's so many of these, tutorials that just kinda get things wrong, and it ends up washing out the the the good information, you know, just kinda in that noise. And so it's like is is many times we can repeat this stuff, get it out there. Like, you know, I'd like to see us, like, repeat this again, like, a a year from now. Just kinda keep reiterating on it. Keep going. This is not the obvious
Dan Shappir [00:08:38]:
gets on again and again in the future. Individually or altogether, just say the word. Obviously, we will enumerate through the pillars and look talk about the positive stuff and the things that that need that should be done and can be done and need to be done. But to make it spicy, I do actually want to start with some of the negatives, if you don't mind. You guys said that you encounter so many bad practices and so much bad advice and bad code. And without naming names, can you give some examples?
James Snell [00:09:17]:
Oh, yeah. We can do whole whole examples. I'm gonna Oh, we can do ago, I did talk.
Matteo Collina [00:09:22]:
Oh, go ahead, James.
Dan Shappir [00:09:23]:
This is a
James Snell [00:09:23]:
couple years ago, I did a talk called broken promises. There there's you can you can find it on on YouTube, and I, you know, created with the work some workshops. Just that, you know, kind of breaks down some of the really bad ways people just get things wrong, particularly around promises because they just don't understand how they work. I had one former consulting customer. When I walked in, was doing a workshop, their their their lead engineer on the team started arguing, with me because he believed that creating new promise was just like creating new thread in Java. So, no, it's completely different model. And this was their lead engineer on on on the team, because they just did not understand, you know, how how this works, and I we just we just kept encountering that over and over and over again, that kind of stuff.
Dan Shappir [00:10:14]:
I just posted the link, by the way. I will also put it in the show notes through that talk.
Michael Dawson [00:10:21]:
So
Dan Shappir [00:10:21]:
Yeah. That's that's pretty amazing. Like, I can understand why somebody might confuse a worker with a thread, but confusing a promise with a thread, that's pretty extreme.
Matteo Collina [00:10:32]:
But look, we can even go to more of a way more basic stuff. K? Mhmm. Like Yeah. Like the let's let's talk a little bit about updating Node. Js. Update do not use, deprecated code. It's unbelievable. Okay?
Dan Shappir [00:10:52]:
The Yeah.
Matteo Collina [00:10:52]:
Companies are not updating Node JS. Like, this seems you know, it's it's bizarre.
AJ O'Neil [00:10:59]:
Once once you deploy something though, it's working, just let it be. Right? I mean, I know a lot of companies are, you know, in some sort of hype cycle where they're just deploying the latest framework every other day, but I think a lot of profitable companies are creating a product. And once that product is good, they're not they're not gonna, you know, rock the boat on it every 5 minutes. They're gonna let it cook.
Dan Shappir [00:11:24]:
Also, you know that old joke about that the developer and his, son walking down the road, and the the the boy says, dad, why does the sun rise in the east? And the father says, it works. Don't touch it.
Matteo Collina [00:11:43]:
Those are good points. Those are good points. But, you know, no one wants to use software that is full of security vulnerabilities.
AJ O'Neil [00:11:52]:
Well, maybe they should stop putting them in node.
Matteo Collina [00:11:57]:
Oh, maybe they should stop putting their products on the Internet then. That's a pretty eastern way to you'd be pulling the plug. It's it's it's secure by default. Okay? Tell
James Snell [00:12:09]:
me so so an application an an application that that has proper isolation around it. And I'd say, if all of the routes coming into that thing are secured and it's not exposed to the Internet, it's just like a long running enterprise application that's there to support existing business processes. If they don't update, they don't update. That doesn't matter because be because they have that isolation and the the the types of threats that are coming at that server, you know, are are much more limited. But if something's out on the Internet, if it's exposed to the Internet, you know, you don't want to have software running that has these security vulnerabilities. You really should update. And as updating, it you know, you can't just quite throw a new version out there. You need to see what other changes are going on.
James Snell [00:12:53]:
Like, we'll deprecate things that we real people really should not use because it could be a security vulnerability, but we you know, but removing it or changing the way it works is too much of a breaking change. And we don't wanna force a breaking change on people. We just wanna strongly nudge you away. Right?
Dan Shappir [00:13:11]:
Yeah. Also, it's not as if those organizations aren't updating their own code. I mean, you know, if if the project is dead, then it's dead. But, you know, we are primarily talking about, you know, living software needed.
AJ O'Neil [00:13:25]:
Dead, profitable. There's a difference between dead and In order to be profitable It's not a suck of engineering resources every week. It's actually making money.
Dan Shappir [00:13:36]:
Yeah. But in order to be profitable these days, you need to be a service. And the only way to justify being a service is continuously releasing updates even if nobody asks for them.
AJ O'Neil [00:13:47]:
Well, I I I was gonna say one thing that circling back. I don't think I have seen anything break in Node since version either 10 or 12. So I recently updated an application. I was so afraid because I'm actually using private APIs in the networking layer. I updated an application, I think, from it was version maybe 12 or 14 all the way up to version 20, and there were no issues. So Node has become incredibly stable probably after version I wanna say after version 10. I think there was a ton of breaking changes in the version 6 or 8. But version 10 or 12, it's it's been incredibly stable, and the likelihood that you'll have to go debug things is is unless you're using an experimental feature, you had experimental flags.
AJ O'Neil [00:14:37]:
But even then, I don't think I've seen any breaks in the experimental features, in in the last several years.
James Snell [00:14:43]:
There's a few. They yeah. They're a few. They come they you know, they're they're usually pretty small, but they they they happen every now and then.
Michael Dawson [00:14:48]:
It it is None of
AJ O'Neil [00:14:49]:
the ones that I use, like Fetch and the there was something in, Web Crypto. And maybe there's some more niche things that are weird like the, what was that it's like a Lifetime's thing. I forget what the name of it was. If it I don't know if it's still a thing, but there was, like, a some sort of a Lifetime y thing.
James Snell [00:15:08]:
And and party
Michael Dawson [00:15:09]:
seem to be party yeah.
James Snell [00:15:11]:
Yeah. Everything about async though too.
AJ O'Neil [00:15:13]:
That that might be like, there's some of that stuff that was super experimental I didn't touch, but anything that already had a web standard was the stuff that I was that that I've been using that's been experimental. It's certainly
Michael Dawson [00:15:24]:
like if you follow the discussions in the in the project, we really are careful about that, and we think carefully. And, you know, if even the ones that James mentioned, we do make some small breaking changes, but we think very carefully about those. We try and understand the impact. And so, yeah, I I think that's one of the things the project has been doing quite well over the last number of years is to try and minimize that. The other thing I wanted to add to what James was saying is, like, it really comes back to risk management. You know, you you can continue to run on older versions, and I think if you've done your risk management, you've done your analysis, like, you may, you know again, back to your point of, like, it doesn't cost any money to leave it just running. So that that isn't that is good. And if you've actually thought about it, maybe you're doing the right thing.
Michael Dawson [00:16:08]:
I think we just don't necessarily see that people are, like, thinking about it enough in terms of, like, should I should I have updated? You know, that's the easy answer is if you you stay on the if you're gonna get the security fixes, or, you know, there's some companies like like the one I work for that will give you longer term support, so you're probably okay then. But, like, we'd probably like to see a few more people either very carefully looking at the risks or sticking to the LTS releases and the ones that are active because those are the ones that, like, the project is gonna help.
Dan Shappir [00:16:40]:
Yeah. But now you're starting to go towards the actual pillars because that's literally one of the pillars. Mhmm. So, I'll just pull us or push us towards that, and let's maybe start going down the pillars unless you guys want to mention something else before we we we do that. Okay. Let's start with the pillars then. So pillar number 1, do not block the event loop. That's an interesting one because it's actually also very much pertinent to the browser, not only to Node.
Dan Shappir [00:17:17]:
And, actually, it's also pertinent to the, Deno and BUN. By the way, I will say that quite a number of these pillars are relevant, or almost all of them are also relevant to Dino and to Bun, I I think.
Michael Dawson [00:17:31]:
Mhmm.
Dan Shappir [00:17:32]:
And some of them are relevant, you know, to whatever server platform almost you're using. You know, they might be relevant if you're using Java or Go or whatever. But, again, we'll be focusing on a node in this conversation. So, again, the first one is do not block the event loop. We've discussed the event loop in the past on this podcast, but maybe it's worthwhile for one of you guys to quickly reexplain or reiterate what the event loop is and why it's so important not to block it. Yeah. I mean, we can can talk about
James Snell [00:18:08]:
it just in very, you know, very high level general terms. You know? You know, a node has its event loop, which is based on libuv. It is structured a particular way. Deno and and and Bon and workers, and so we you know, they all have event loops that are they work slightly differently. They have different phases, different, you know, slight you know, slightly different implementations. So they all work slightly differently, but they all have the same fundamental concept of it's gonna be monitoring the system for, well, you know, certain events, IO, hey. I wanna read a file or I've got a network connection or whatever. And as it's turning, it's gonna, you know, say, oh, I gotta I got some IO.
James Snell [00:18:49]:
I'm gonna fire a callback. That callback is gonna go off and run some JavaScript and what's important to understand is that while that JavaScript is running the event loop is not it pauses while you go off and run that JavaScript and then when that is done running, it comes back and the loop continues. It doesn't matter what platform you're on. That's how it works. Unless you're using worker threads, but you have multiple event loops running on different threads, when you're whenever you're running JavaScript, nothing else is running. Right? You're not going out and pulling IO. You're not, you know, looking for you
Matteo Collina [00:19:23]:
know,
James Snell [00:19:23]:
you can't go off and accept a new connection. Yeah. That kind of stuff. Right? So it you know, it's you have to make sure that that JavaScript that you're running can return fast enough for that event loop to turn around and and do something
Dan Shappir [00:19:38]:
else. Now on the browser side, it's it's maybe less catastrophic, but it's often more obvious when there's a problem with the event loop because user interaction starts to get junky. Somebody clicks a button, and, the UI doesn't respond because the browser is too busy processing the JavaScript for a previous event. What's the negative impact in node when you, don't process stuff out of the event loop quickly enough or when things stay in the queue for too long?
Matteo Collina [00:20:19]:
I have a very nice talk on this, okay, which I recommend everybody to watch. I'm going to pass it. I'm going to summarize and then pass it into into the chat for everybody to, to to take a look. Okay? So the, the gist is is very simple. What is that? What happens? Okay? You take, the event group is be gets busy. Okay? The problem, it doesn't you say, well, the event group is busy. What problem it can be? Okay? Well, generically, if there's only one user, k, which is, for example, the case for, deployment on workers or an AWS Lambda, this is essentially the impact is very limited. Okay? However, you are also missing out on the key feature of Node.
Matteo Collina [00:21:14]:
Js and JavaScript itself because you can, you know, supporting multiples at the same time allow you to maximize the use of the resource of that single process. So what happens is that once the amount of load goes over, and there's a little bit of math involved, goes over a shared threshold, The response time of your application will start getting, will will start looping into we start growing in an exponential in a in an exponential fashion. And therefore, at that point, you are your application will stall completely very quickly and not responding, not nothing, spinning wheels. Typically, the problem is if I send a request, okay, to you, you want the you if you are if you're done a good job, you are going to respond your server is going to respond in, I don't know, 200 millisecond, a second, 2 second. Okay? After what's the threshold after which I stop responding? Okay. I stopped I stopped waiting for a response. Okay? But the problem is then when you receive an an HTTP request in node, you you know, Node. Js has received that request, and we continue processing that request up independently of the fact that the of the user on the other end as, is still there.
Matteo Collina [00:22:46]:
Okay? You can detect that. You can handle this with our signals and a bunch of other stuff, but it Yeah. Definitely not
James Snell [00:22:55]:
Yeah.
Matteo Collina [00:22:56]:
Definitely not common. Okay? So and the the genetic result is and when you Node. Js reach a certain level of load, it become very much unresponsible. The your application become unresponsive completely. And this is a massive, massive problem.
James Snell [00:23:13]:
A great example. You know, based on former customer, I'm not gonna name any names and such, but we were we were called out to do some consulting work for them because their node application was very, very slow. They were getting a whopping 4 requests per second production. Like, what the hell are you doing to get only to only get 4 requests per second? Well, what they were doing They're
Dan Shappir [00:23:35]:
calculating pi to the trillionth digit digit on every request.
James Snell [00:23:41]:
Almost worse. So, they they were using an old version of Apollo, that was not very, performance optimized. Every GraphQL query that they would receive was very complex, and it ended up being where they would do, like, 5th 10 to 15 sub requests on the back end. That, back then, the way that Apollo works is it would receive the request, it would parse it, generate the AST, walk the AST, go off and submit all of the, sub requests, wait for those to return, and then would have to go through and do this this process of reconstructing the response. Unfortunately, these these queries were so complex that it was blocking the event loop. All of that processing was was synchronous. Alright? Now waiting on the sub requests, that was asynchronous, The actual parsing and walking of the AST was fully synchronous, and they were blocking the event loop from progressing every time that happened. And they were blocking it by so much that, you know, it couldn't get around to take the next request.
James Snell [00:24:39]:
Right? The other problem they were encountering though is roughly maybe about 15% of their, of their requests were failing with timeouts. I'm like, you know, we don't we don't understand why these are failing with timeouts. Well, what would happen is they would send, like I said, 10 to 15 back end requests. Right? You know, sub requests. Those would go to the back end systems. Those systems were responding quickly. Right? And and and and, you know, having, responses pending in the IO queue, in in in the the node event loop. But if you look at the phases of the node event loop, what you'll see is almost right before we poll for a pending IO, we we check timers.
James Snell [00:25:25]:
Right? You know, in in that loop, we always check timers first. What was happening is that the event loop was being blocked for so long that by the time the event loop turned and came to, and broke the timers, even though that those responses the sub request responses were waiting to be read, the timeouts on the sub requests would would fire and cancel the entire thing.
Dan Shappir [00:25:47]:
Oh, no. So it
James Snell [00:25:49]:
was just like this compounding problem that all of this synchronous activity blocking the loop from actually advancing IO tripping itself up.
Dan Shappir [00:26:00]:
If I'm thinking about it, I can basically, like, perceive of 2, like, main problematic scenarios here, and correct me if I'm if I'm wrong. One scenario is that even though events are pre are being handled relatively in a timely fashion individually, the rate in which they're coming in is so high that, the, server is simply unable to complete the processing the events at the rate that new events are coming in. That's that's problem number 1. And problem number 2 is that regardless of the rate that events are coming in, sometimes the processing is so lengthy that the loop is just being blocked for so long that it's making the system and the system is unresponsive during that time, that that causes problems because other events time out or not processed in a sufficiently timely fashion, all sorts of problems. So the the the service might be even mostly not busy at all, but whenever something comes in, it just gets stuck for for for too long a period. Am I understanding correctly?
Matteo Collina [00:27:20]:
Yes. Yes. Yes. And if that event opens happens too often, it gets into a catastrophic failure. And most node go ahead, Michael.
Michael Dawson [00:27:32]:
I was gonna say, like, the the event loop's really optimized to do lots of short things. And, you know, you you talked about the first case of things coming in too quickly. Well, may node can scale to take a lot of incoming requests as long as you quickly hand them off to something else to, like, you know, if you come in, you take a request, you hand it off to the database, and you do that asynchronously, it can scale to lots and lots of things coming in.
James Snell [00:27:57]:
And
Michael Dawson [00:27:57]:
I think as as Mateo was kinda saying, but if you get to a point where you're you're trying to do too much in the event loop itself because you're you're effectively sharing a single thread, you're now gonna slow everything down and it it falls over a cliff at at one point.
James Snell [00:28:13]:
So, you
Michael Dawson [00:28:13]:
know, if you've got longer running tasks, you really wanna push them to worker threads. And a good example that I I I I think is Or to other servers. Or to yeah. Or to other servers, but
Dan Shappir [00:28:23]:
Like a microservices architecture or something.
Michael Dawson [00:28:26]:
Exactly. The The the one thing I think is kind of interesting is even if you have your microservice, you say, okay, I'm gonna make a microservice for my very long running job. You still don't wanna block the event loop for that microservice because the main event loop, because, well, what if you deploy that microservice to Kubernetes? Kubernetes is probably gonna have a liveness check. And, well, how is that liveness check gonna run? It's gonna have to hit that main event loop and say, hey. Are you still alive? And if
Dan Shappir [00:28:52]:
you don't Sorry. I literally had this problem. Okay. Yeah. At the company that I worked at, again, without naming names, we were actually using, Prometheus, the Prometheus client. And without going into reasons, the Prometheus response that was being generated was huge, and it was a huge string being serialized. And that just took too long. And if that happened while the liveness check happened to come in, it could literally cause the liveness check to time out and cause Kubernetes to kill that instance.
Michael Dawson [00:29:33]:
Yep. Mhmm. So you you always wanna push your long running jobs onto worker threads so that your main event loop can respond quickly. Yep.
James Snell [00:29:46]:
And this problem is is not unique to Node. Not by any stretch. Now in other run times, it manifests differently. Like workers, you know, we have a completely different threading model and workers to know. Every request is basically running on its own thread coming in, we can still accept other requests and that kind of thing. But, an isolate, a particular worker might be used by multiple threads. So whenever one request is being processed on one thread, right, no other threads can use that isolate that can can use that, you know, that particular instance, and we have to share these. So we have these things that are called, you know, basically lock contention.
James Snell [00:30:25]:
It's waiting for that locks you know, waiting for that isolate to be free so I can use it on this particular thread, and it jumps around. If it it's a different mechanism, but has the same effect of blocking other things. If one particular request has too much synchronous processing that goes on for too long, then other threads can't acquire that lock and can't progress. They can't, you know, run their own JavaScript, and and it ends up being the same basic effects block in the node event loop. So you just gotta
Dan Shappir [00:30:55]:
remember think about lock soft and sorry. You just just just that I'm I'm not used to thinking about locks so often in the context of JavaScript. That's all I wanted to say.
James Snell [00:31:05]:
Yeah. I mean, what what they're there, you know. And and and the the key concept here for this particular pillar is, yes, run JavaScript all you want. Just do it in short span. You know? Short first. Don't do these huge, long, synchronous processes.
Dan Shappir [00:31:19]:
So, basically, either push processing off of the main node thread to workers, to microservices, whatever. Don't and don't wait on them. Just send it and wait for their synchronous response, or break your, long running JavaScript into multiple shorter segments. Like, it might be anything you know, the the set time out 0 for the win.
Matteo Collina [00:31:50]:
The setting mediate, typically, the task that the the company
Dan Shappir [00:31:53]:
is doing.
Matteo Collina [00:31:55]:
But yes. Unfortunately, yes. Okay? In that way, other things can be scheduled in between. K? So that's the gist. But, genetically, I would say that we do have enough fake technologies right now to run things easily on worker threads that you should just be using threads. Like, literally, most developers don't think, that Node. Js is multi threaded these days. It has been since 2018, and most developers thinks, you know, they're still reading that tutorial for 2015.
Matteo Collina [00:32:27]:
So, that's a problem. I have to say that there is one issue with
Dan Shappir [00:32:33]:
it, and I know that there are several proposals that are looking to address it. But so far, it still exists, and it's more of a Java script issue than a node issue, and it's that serializing stuff across workers can be sometimes more expensive than the actual work that was offloaded. Like, serializing and deserializing each way can sometimes be more expensive than the actual work that you offloaded if you're not careful.
Matteo Collina [00:33:05]:
Of course. But it it means that you need to offload stuff that is bigger, essentially.
Michael Dawson [00:33:10]:
Yeah. Yes. And and there and
James Snell [00:33:11]:
there are ways around that, you know, with with, you know, like, shared array buffer and some of the shared data structures we have. So
AJ O'Neil [00:33:17]:
Yeah. So Node has the ability to run multiple processes. So you can you can fork and you can I don't remember exactly I kind of forgot it because it turned out not to be useful for this very reason that the the communication between node processes of doing the JSON stringify and the JSON parse makes it so that you should probably never ever do that? And the only way that you should be using node, if you're gonna use multiple processes, not is not its its child process forking mechanism, but rather, you just run multiple processes. They handle multiple requests and let them, you know, do Depends on everything. Database separately and stuff. Yeah. What where where would that where would that be profitable? Where where would it actually make sense to use that oh, cluster. It's called node cluster.
AJ O'Neil [00:34:10]:
Right?
Michael Dawson [00:34:11]:
Yep. Is that what it's called? Yeah.
AJ O'Neil [00:34:13]:
Yeah. I think it's kind of a secure feature most people know about.
Michael Dawson [00:34:17]:
Yeah. I think today,
James Snell [00:34:18]:
I would you're doing. Okay.
Michael Dawson [00:34:20]:
I was gonna say, I today, I would defer to other things like, you know, Kubernetes will manage multiple instances of your node application, each which should be stateless. So, like, if you wanna scale, there's lots of non node specific ways of scaling processes out so you can have multiple copies of your your micro ins of your micro service. So that's why I wouldn't necessarily be using the cluster module on its own anymore. Yeah. So it's really like, you know, I would typically scale using those technologies when it's a matter of just needing more than one thread's worth worth of, you know, throughput. Because you could have lots of little tasks, but you just still can't handle all those tasks on on a single thread, in which case, let's scale out to multiple processes. But if you have long running tasks, even if you have enough to to maybe only take 50% of your your single CPU, you don't wanna do those on your main thread loop. You wanna still push those to workers because
Dan Shappir [00:35:14]:
you
Michael Dawson [00:35:14]:
don't wanna be blocking all the all the work based on those lower or longer transactions. Right? Even if there's, like, 1 in 10, every 10th second, you don't wanna have something that takes a really long time and slows everybody down.
Dan Shappir [00:35:26]:
Yeah. I think it was Jake Archibald that said it in the context or maybe it was, Surma that said it in the context of browsers that one of the reasons that you want to offload things to workers is not so much sorry about performance. It's more about consistency, that you don't want all of it. Yeah. Like, every x task to suddenly block your system for too long. I do have to say, though, that in my experience, most of the work that I've seen done on node is mostly as quote, unquote, middleware. So very often, there's no no so much heavy lifting being done inside the node service itself. Let's say it this way.
Matteo Collina [00:36:05]:
Are you sure, Dan?
James Snell [00:36:08]:
No. I'm not. Now I'm scared.
Matteo Collina [00:36:10]:
Like, let's let's if you if you take a look at what the, all the front end meta frameworks are doing Mhmm. Lately, they all of them, they are massively blocking the event loop. Like, they
Dan Shappir [00:36:27]:
simply because of all the all of the rendering code, the all the service that rendering stuff?
Matteo Collina [00:36:33]:
Yes. So in that scenario, if you're ready, I have a very expensive rendering pipeline, and you also need to do some, data processing, data mangling that can take some CPU time, you are really, really you really, really want to push it somewhere else. K?
Dan Shappir [00:36:52]:
And do they? Well,
Matteo Collina [00:36:56]:
not on the not on the tutorials, but, yeah, you can, But not on the main to not on the main to do.
Dan Shappir [00:37:01]:
No. I'm asking if from your experience, the framework makers are doing the the the best, you know, the best that they could do to offload stuff.
Matteo Collina [00:37:12]:
No. They they are in in order
James Snell [00:37:14]:
to to let me get better.
Matteo Collina [00:37:16]:
It's it's getting better and better and better. And I think it's it's not like, a lot of it comes around on the marketing side versus the framework itself. Okay? Then nothing in the frameworks blocks you to do certain things. Okay? But it's more about how they market the the the frameworks and the products that cause like, they they make, the they make those applications. You know? They teach developers using their frameworks very often that they could do certain things, and those certain things will work very well up until a point. And then it what they won't work anymore. But they then don't tell you that point.
Dan Shappir [00:37:57]:
Yeah. And and the Prometheus example I think I gave is is a pretty good representation of that.
Matteo Collina [00:38:03]:
Yeah. For for that, okay, what we have recently been done in, we have launched a product called the Vat application server. And what we do is we keep we use one worker thread. So we run the applications in in the application in a worker thread, and we keep the Prometheus in the main thread. So in this way, we can have the monitor. Okay, not affected by the, the application itself. And in this way, you can keep things, we can keep things responsive and up. Okay? And and be able to monitor them correctly even if the application is under heavy load.
Dan Shappir [00:38:46]:
Yeah. By the way, just to toot my own horn, I actually contributed back into the prompt client project and optimization that basically just reduced the the runtime cost of of serializing the string by something like 50%. So
Matteo Collina [00:39:00]:
Good. Thank you.
James Snell [00:39:01]:
That serialization thing. And going back to, you know, AJ's, you know, original point there about the cost of serializing the data back and forth across these boundaries. Alright. You know, it doesn't matter if you're using a worker thread or a a child process or whatever. IPC, it doesn't matter. Serialization and deserialization, back and forth, those boundaries always has a cost. You can use, you know, faster serialization frameworks, so protobuf for CAP and p versus you know, instead of serializing everything as is is JSON, but you're still going to have a cost. So it's like anytime you're you're distributing this load, you you need to do you know, take effort, take steps to minimize the amount of serialization, deserialization you're gonna do.
James Snell [00:39:42]:
If you're using a child process, rather than sending a a large chunk of JSON, just pass the FD. Right? And let the let that child process, you know, read the data off the, off the network and do its own, you know, some parsing or whatever. If you're doing worker threads, use shared data objects like shared array buffer rather than things that need to get copied and serialized using, you know, structured clone. The more of those kind of things you do, the more effective this this load distribution is going to be because you're not gonna eat the you know, eat eat up all your your performance gain on serialization, deserialization cost.
Dan Shappir [00:40:18]:
So We've been stuck on the first pillar for such a long time. It's pretty obvious we won't be able to run through all the pillars, which is just a great excuse to to invite you all over again. But still, unless somebody else wants to say something about the first pillar, I think we'll move on to the second one. Is that okay with the I think
Matteo Collina [00:40:37]:
we have covered the second one too. You know? Yeah. We have. Yeah.
Dan Shappir [00:40:41]:
Yeah. To an extent, we have. It's, monitor note specific metrics and act on them. This is one of those recommendations which is true everywhere, for every system, not just for node.
James Snell [00:40:53]:
It's I I will say that be monitoring. Yeah. I don't see on this particular pillar. There there there's there's one here that is worth calling out that most people, most node users, even even the long term ones, aren't familiar with. Event loop utilization. Folks still talk about event loop delay. Right? And that is a different metric. Event loop utilization is a relatively new concept.
James Snell [00:41:15]:
It's it's been there for a couple years. Most people don't know about it. And it it's a measure how it's
Matteo Collina [00:41:20]:
4, James. Yeah. Maybe 4.
James Snell [00:41:21]:
Yeah. The event loop utilization is a measurement of how effectively your event loop is processing tasks, versus waiting for things. And it's it's a much more accurate metric of how, well your application is performing than event loop delay. So everyone
Dan Shappir [00:41:41]:
really should be Before you continue yeah. Because I would like you to explain it. I'm familiar with the term with the metric called event loop lag. Is that just an alternate name for event loop delay?
James Snell [00:41:54]:
Yeah. That that I would think so. Yeah.
Dan Shappir [00:41:58]:
So event loop lag, which I knew, was basically what you described. It's the like, looking at the meantime or the 90th percentile between when an event gets into the queue and until it gets processed pulled from the queue in order to be processed. And, obviously, there, the statement was, you know, you want the mean value or the 90th percentile or whatever to be basically as low as possible in order for the system to be responsive. But you're talking about something else. You're talking about event loop utilization. Can you explain that metric to us?
Matteo Collina [00:42:34]:
Yeah. I mean, there there's a
James Snell [00:42:36]:
a a few things that go into it, but it's basically a ratio of how how much time your event loop is spending doing things versus just sitting idle waiting for things. So let's say if you have an, event loop that is just going off your application is just going off and scheduling a whole bunch of IO, and then it has to wait a long time for that IO to do anything. And in between those times, it's not actually processing anything else. Right? In that case, your event loop is not being utilized effectively. It's spending most of its time being idle waiting for stuff. But if that event loop is able to turn over very, very quickly, accept a new request accept a new request while it's processing other things, While it's waiting for that other stuff to happen, if it's able to keep processing things, then you're gonna see a higher utilization. That basically means your event loop is is doing more, more efficiently. I hope that's very there's a whole Yeah.
James Snell [00:43:36]:
Whole paper on it.
Dan Shappir [00:43:38]:
Okay. But I I'd be happy to have a link to that paper, but one thing does concern me. It does seem that if I pull in, like, the first event and that triggers an infinite computation, which means all the other things are just stuck in the queue forever, my event loop utilization would still appear to be great because I'm just processing forever. Like, is that am I or am I missing something?
Matteo Collina [00:44:06]:
Yeah. The the missing some of
James Snell [00:44:08]:
the details. It it takes some of those those things into consideration. The the paper goes into a lot more detail, and this was done by Trevor Norris, at NodeSource. The the the the blog post he wrote on this initially, introducing it answers pretty much all the questions about it. Right? It it is one of the best research paper
Matteo Collina [00:44:26]:
Consider the you can you can take, event loop utilization in in a slightly different way. Okay? Consider this. At event loop delay or event loop lag, k, it's a metric, k, that you can measure after there is a lag. Okay? Mhmm. However, you only have a lag, okay, if your event loop is very busy.
Dan Shappir [00:44:49]:
Correct.
Matteo Collina [00:44:50]:
Okay? Event loop utilization is able to tell you that the event your event loop is getting busy. So you can act on it way sooner than than the event loop lag. Okay? In fact, it's a much
Dan Shappir [00:45:05]:
Basically, what you're saying what you're saying, if I'm taking too long to process user requests, but I have very few users, then I might not notice that I have a problem. And by the time I I do realize I have a problem, it's kind of too late in a sense because users are already suffering.
Matteo Collina [00:45:23]:
Yeah.
Dan Shappir [00:45:23]:
What you're saying is with event loop utilization, I'll be noticing it much earlier and be able to respond to it, you know, in advance. That's really interesting. I I very much would like to look at the paper.
Matteo Collina [00:45:37]:
It's,
James Snell [00:45:38]:
the other the other thing that it does
Matteo Collina [00:45:40]:
Go ahead, James.
James Snell [00:45:41]:
I'll just mention real quick. The other thing that it does is it tells you how well you're scaling, and it gives you a much more accurate scaling point. So, a lot of applications previously would look at CPU usage. Right. And when when node process is primarily just one thread, one main application thread before, we had worker threads, That was an okay measurement, but it was still pretty noisy. As soon as we introduce worker threads, the CPU monitoring just goes out the window because it becomes way too noisy because you're, you know, because it's it's not fine grained enough to be able to show you individual event loop processes. The event loop utilization is per event loop, so it's per worker thread, and it gives you a much better signal at where you where and when you need to start scaling your application to multiple processes and multiple worker threads. You know you know, better than any other metric that I've seen, this is the one that gives you the the the the best accuracy for that.
Dan Shappir [00:46:41]:
And monitoring systems these days, do they expose this metric?
Matteo Collina [00:46:47]:
Well, platformmatic does. So if you sorry for the for the pun here, but, yeah, we our product our our initial product, absolutely. But also all our open source expose this metric on as part of the Prometheus integration. So you can essentially take it and consume it and so on and so forth. The important part is that you want you want to, set your outer scale to, look at this metric versus CPU. Okay? If you if you look at CPU usage, you are typically, it's too laggy. K? Once once you see once the auto horizontal part of scaler see that stuff, you are you are already in trouble. Okay?
Dan Shappir [00:47:32]:
And with But it's not a metric that's built into node or whatever. There's no, like
James Snell [00:47:38]:
No. There is.
Matteo Collina [00:47:38]:
You can do.
Dan Shappir [00:47:39]:
There there's I there's
James Snell [00:47:40]:
an API for it. It. Yeah. Yeah. There's an API built into it, and directly in the note as part of the purpose API.
Matteo Collina [00:47:46]:
You need to enable it in prompt client.
Dan Shappir [00:47:49]:
Very cool. Very cool. We'll definitely look at it. Thank you for that. Anything else about pillar number 2? Okay then. Moving on to pillar number 3, news node LTS versions in production. I think it it even though people listening to us should be familiar with Node, I think it's worthwhile to mention what Node LTS versions actually mean.
James Snell [00:48:17]:
Mhmm. Yep. Long term support. This is basically Michael,
Matteo Collina [00:48:20]:
you want to take it?
Michael Dawson [00:48:22]:
Sure. Yeah. Like, long the you you can go to the the website. There are the on the GitHub. It's like no JS slash release. It'll have our our schedule. The you know, every every it's very predictable release schedule. We have a current, which happens every April October, and then every even current gets promoted to long term support.
Michael Dawson [00:48:44]:
Long term support means, I think, it's 30 months of support. So it lasts from, you know, October this year, for example, to April two and a half years from now. And the e so the odd currents, they only have 6 months of support. So, you know, why why we say you really wanna stick to the long term support versions is that, you know, that's the longest period of time that you can sort of be on a version that's not going to go out of service and back to AJ's point of, like, we don't wanna change things any anytime. We don't wanna change them because it costs us money. Right? So you wanna basically look at the release schedule and pick the LTS. It's gonna give you the longest runway, and, you know, I I'd also say, like, schedule. You don't have to move up to every LTS because we have multiple overlapping LTSs.
Michael Dawson [00:49:32]:
We either have, like, 2 or 3 usually going on at the same time. So if it was me, I would basically say, like, okay. When do I wanna go into production? Let's plan to have the closest LTS. And then, you know, 2 years later, I should plan on, like, okay. Now let's plan for upgrading that particular version to the next LTS. There are multiple phases in LTS as well. There's, like, an active phase where we we back port changes quite quickly. So if you wanna get new features, they still go into those LTS releases.
Michael Dawson [00:50:02]:
But about after the first, and I'm thinking it's 8 months ish now, I'd have to look exactly at the the numbers. It then splits into maintenance where things are more, like, as needed security security fixes, that kind
James Snell [00:50:15]:
of stuff.
Dan Shappir [00:50:17]:
Why do non LTS versions even exist, and why would I ever use one of them?
Michael Dawson [00:50:23]:
See, the there there are people who wanna be on the bleeding edge, and so those ones give you based on our our our schedule, we feed things into those non LTS versions first. So if you want to get the very latest greatest, you can try them out there. And we do appreciate that people test them out for us and give us feedback and you know? So if you wanna take advantage of a new feature, we we really do people want want people to try those out and give us that early feedback.
AJ O'Neil [00:50:51]:
And there have been cases where I've there have been cases where I've had to use a non LTS because there was a critical feature particularly related to web crypto or fetch or one of those standards that is cross platform standard for JavaScript that was only available at first in the in the non LTS. Right now, for example, Nodes ESM support has finally completed, but it won't be available until, what, v 24 without the the flag? So I I'll probably update to v
Michael Dawson [00:51:29]:
2020
Matteo Collina [00:51:30]:
Are you sure?
Dan Shappir [00:51:33]:
It'll be 23.
James Snell [00:51:33]:
Yeah. Are
Matteo Collina [00:51:34]:
you sure, AJ? Now I have I have a very good news for you. I have really very good news. We are likely thinking of back porting it to 22.
AJ O'Neil [00:51:46]:
Yeah. Oh, sweet. That's great. Yeah. That's that's that's amazing. Yeah. Because that that's something I have not been using ESM because, you know, like, why would I publish something to NPM that breaks everybody else's stuff and everybody else has to transpile, but then all those people are using bundlers anyway? Like, you know, ESM just didn't make any sense. And then when I saw that, I was like, yes.
AJ O'Neil [00:52:06]:
Finally, I get to to not have to screw around with all this, you know, window crap.
James Snell [00:52:13]:
This raises this raises the good point. It's like, why do we have this, you know, the schedule? You know, back if you think back to when before Node and Ios. Node was originally going way too slow. Ios came in and was going way too fast. So this LTS schedule was a you know, let's find a middle ground. Like, we're going to have 1 LTS per year, but why do 2 majors? And the reason for that is because the ecosystem needs to be able to have these features out at a faster rate than only one release per year. And so, you know, the the the short term, like, odd numbered, currents, those are primarily to help the developer ecosystem in Node, not the, like, enterprise, you know, production users. It's there to help, like, the the module developers in the ecosystem that that are producing all of these dependencies keep up on the rate of change and allows Node to be you know, to know, like, what's actually being used.
James Snell [00:53:10]:
How does this be evolved? You know? You know, might actually get used to these things before it goes LTS, before it goes where we have to maintain something long term.
Dan Shappir [00:53:18]:
And it's still considered to be a stable version, an official stable version, so I'm not, like Yep. Working on some beta or whatever. I am working on an official version. I just get the the, let's call it, modern or bloody bleeding edge features sooner, and I don't have to wait a full year Yes. For for that stuff. And I can have it ready in advance of that LTS release.
Michael Dawson [00:53:41]:
It still respects SemVer, so you you can you can expect that there shouldn't be really any breaking changes.
Dan Shappir [00:53:47]:
Mhmm.
Michael Dawson [00:53:47]:
But features go in more quickly. And it and it really does help us in terms of, like, the versions we promote to LTS. It's great to have that 6 months as a current because that really helps us find out, like, are there any things that we missed in terms of, like, did something was it more breaking than we expected? And, you know, means sort of that 6 months means that by the time we go to the LTS, we have a much better chance of it just being boring for everybody, which is what we like.
Dan Shappir [00:54:14]:
I really want to be respectful of all your time. We are nearing the time usually where we start pushing towards picks. I'd love to continue this conversation for now. It's also easier earlier for me because, we've switched to Daylight Savings and you guys well well, off of Daylight Savings and you guys are still, at least in the states, are still there. So I don't know how long you guys can go. Do we have another 30 something minutes, or do we need to start thinking about wrapping up?
Michael Dawson [00:54:47]:
I got time. Yeah. I'm all I'm okay.
Matteo Collina [00:54:50]:
I'm okay.
Dan Shappir [00:54:51]:
Okay. Let's keep on going at least for a while. Let's see how far we can push it. Anything else about this pillar before we go to the next one, which is a whopper? Okay then. So pillar number 4, it's automate testing, code review, and conformance as much as possible. Again, this is like a absolute truism of software development that has you know, it's true for a node, but it's practically true everywhere else in the world. By the way, there's this click, so I don't know where it's coming from. But, guys, please be aware that there's, like, this clicking sound going on.
Dan Shappir [00:55:33]:
Anyway, so what do we have to say about automating tests and code reviews and conformance that's node specific, or is it just, you know, do it?
Michael Dawson [00:55:48]:
I I think what my perspective on this would be is that, you know, one of the advantages why people we hear use Node. Js is that they can move really quickly and they can innovate quickly. For me, that's great if you can move quick quickly, but it makes your testing and your regression test all the more important. So while this is very important in most cases, it's even more important when you're moving fast. And because Node lets you move fast, that's why it's so relevant to you.
Dan Shappir [00:56:18]:
I I'm total I totally agree. Part of my job at almost everywhere that I've worked in the past over a decade, is going into existing projects and starting, you know, to mess with them and literally break them. And, like, the difference between between having tests and not having tests is like life and death, literally. It's it's like, am I how confident do I feel even going into this project?
Michael Dawson [00:56:48]:
Yeah. It's like if you can make if you can make a change, run the the test suite and feel pretty comfortable that it's not gonna the world's not gonna light on fire, that's what lets you move fast. Because if you don't, if you're like, oh, I made a change, but nothing's testing this, you're you're always very cautious, right, I think, and you're not gonna go as fast.
Dan Shappir [00:57:09]:
Now you did differentiate between, like, the 3 different kind of tests that people usually talk about, which is unit tests, integration tests, and end to end tests. Now I'm curious, like, because I I hear people different people putting different emphasis on different types of tests. So I I hardly ever encounter people who say, you know, you don't need tests, but I do encounter people who say, you know, it's all about the end to end tests. And other people are saying, no. It's all about the unit tests and and so forth. So I am curious where you guys which camp you guys fall in, if you even do fall in a camp.
James Snell [00:57:54]:
I for for me, I don't necessarily care about the type of test. I care I care about the test coverage. And I know a lot of people, you know, have a problem with chasing, like, you know, complete test coverage and stuff.
Dan Shappir [00:58:06]:
Or measuring test coverage.
James Snell [00:58:08]:
Right. I don't care necessarily what kind of test it is. I care about is this line of code tested. And too often, you know you know, folks will only test the happy path. You know, they'll only they'll write their test based on what they want the code to do, not based on what the code actually does, and they end up missing, like, you know, coverage on half the branches that that that their code, that their code takes or could take, and then they get it into production or make some kind of refactoring change and things just break.
Dan Shappir [00:58:42]:
My one of my problems with end to end tests, which on the face of on on on the face of it, end to end tests, like like, they have, like, they could have been the best tests because they literally test the system as it should work. But there are 2 from my perspective, there are 2 main issues with it. 1 is that they can run pretty long, which means that people run them less often. And the other problem is that, testing coverage with end to end tests or achieving good coverage with end to end tests can be pretty challenging.
James Snell [00:59:22]:
I I think Yeah. Because a lot of times
Michael Dawson [00:59:25]:
I was gonna say I think
Dan Shappir [00:59:26]:
I'd agree with kind of
Michael Dawson [00:59:27]:
the challenges. Like, the I think the end to end tests, like, along with that is it's sometimes harder to figure out what went wrong or, like, you made a tiny change and you only if if you only find that in your end to end test, it's probably gonna be hard to figure out what that tiny change is versus At
Dan Shappir [00:59:45]:
least you found it before production.
Michael Dawson [00:59:47]:
Yeah. No. No. So so so I think it's a balance between the 2. Right? Like, I think having unit tests, which gives you really good coverage of the very specific things, will help you find, like, hey. I just made a commit, and I broke something, like, on the you know? But broke something small, I can find that very easily. And so you want you want as much unit testing as you as you as you can afford to cover, you know, find those things, but then you still definitely need the end to end tests. But you probably don't need to test every single thing in the end to end test because, like you said, that quickly becomes too long, and, you know, you can't run it as often.
Michael Dawson [01:00:24]:
Right? So it's finding that right balance between, you know, having your unit test that can fill only they will be able to cover everything in the end to end style, but covering as much as you can and then as much of the the end to end testing is as practical so that it still gets run on a regular basis.
Dan Shappir [01:00:39]:
Also, it's much closer to the actual code, so you're much less likely to miss branches at least at the unit level.
James Snell [01:00:46]:
Right. And a lot of times, the integration tests, are incapable of of, testing particular branches, like, particularly if they're edge cases or, you know, should only happen in, like, critical failure situations where your end to end test isn't actually able to trigger those. Right? Because it's it's it's meant to be some internal failure or IO is failing in some case. Those units are going to actually make it make likely.
Dan Shappir [01:01:14]:
Yeah. We all know the remedy to a to a critical problem, which is console error.
James Snell [01:01:22]:
Mhmm. Of course. Yeah.
Dan Shappir [01:01:26]:
Okay. Anything else we want to say about tests? Any recommendations about the systems you guys use for testing? Any particular system or mechanism I should be using as a node developer?
James Snell [01:01:41]:
Use node tests. Use the the new test framework built into the runtime.
Matteo Collina [01:01:46]:
What I can tell is what not to use. Okay? Don't you jest. Make yourself a fan. No. This is true. Okay? If you're building a node system, jest has a lot of good features. If you're building, if you're using it for some of the, front end, meta frameworks. Okay? But, if you're building a node app, an API, or something like that, use, don't use it.
Matteo Collina [01:02:12]:
I I recommend because you cannot test a 100% of the branches with it, and, therefore, it completely defeat the purpose of of a testing framework. So if I can't
Dan Shappir [01:02:25]:
Why is that, by the way?
Matteo Collina [01:02:26]:
Because in monkey batch is global. So, if in the node, emits an error, you know, one of its own APIs, in the however, the error object did not create is different than the one that, Jess has put in the global. So if you do error, instance of error, it will turn false even though it's an error. You you don't know what Now now it
Dan Shappir [01:02:53]:
well, now we have, the the JS spec, we have error is error.
Matteo Collina [01:03:00]:
That's I
James Snell [01:03:01]:
mean, that that should that should help. But but, yeah, with with with Justin, you know, in the front desk, Jasmine, a couple others, you know, had this issue before where the test ends get the test you write ends up testing the mock rather than testing, you know, the actual run time, the actual code. We had this problem in workers. You know, for the longest time, we're doing local tests, you know, because our test framework originally, like that client side part, the original version of MiniFlare, was actually running a node. So when you would go to develop your your worker and test it, you were actually testing it against nodes implementation of something like readable stream, and then you actually go to run it in the run time and oops, it breaks because, you know, we have slight differences. You know, we're we're getting away from that now where you can actually test on the actual production code. But a lot of these test frameworks like just have that fundamental problem where you're not testing the thing you're actually running.
Michael Dawson [01:03:54]:
And I think Matteo's point might be, like, it it has some advantages if you're, you know, closer to the front end side of things. But if you're really just a a node microservice, you might be better served by something that's more node focused versus versus that.
Dan Shappir [01:04:09]:
And in that case, just use the built in node testing framework.
Matteo Collina [01:04:14]:
Yep.
Dan Shappir [01:04:16]:
Cool. Okay. Moving on to the next one. And I think you know what? We'll see if this is the last one, or we'll manage to get to number 6. It's kind of stopping in the middle if we if we stop in this one, and then we'll give us an incentive to do another episode. I would love to have you guys on again. This is such an awesome conversation. Okay then.
Dan Shappir [01:04:41]:
Number 5. And, again, this is just a golden rule in software development of but I think it has special meaning in the context of node, and that's avoid dependency creep. Can we explain what dependency creep means in general and what it means specifically in node?
Matteo Collina [01:05:03]:
So this is, probably one of the most misunderstood practice, especially, lately. It's, like, the node has been had had the success it had only because it was able to solve one specific problem. In fact, node didn't do it. Npm did. It it found a way to to do software reuse at massive scale. Okay? And by by in in what what's the mechanism? Well, by allowing more
Dan Shappir [01:05:39]:
And it turns out that your substantial portion of that reuse. Pretty much.
Michael Dawson [01:05:45]:
Alright. Is
Matteo Collina [01:05:46]:
it I don't know if it's a good thing or a bad thing. Okay? I am one of, like, I think, actually
Dan Shappir [01:05:52]:
You're that guy from the text you're the that guy from the xkcd strip about that,
Matteo Collina [01:05:59]:
Visibly, in the
Dan Shappir [01:06:00]:
Yeah. Visibly, he's about Italy. Yes.
Matteo Collina [01:06:04]:
So, the that's it. Okay? So it's, avoid dependency creep. So Node. Js had the massive success due to, this software use. It allows you to, for example, use different version of the same libraries in different, dependency trees of your app. K? This means that you can have, and this happens very often, readable stream 1 in your codebase, readable stream 2 in your codebase, readable stream 3 in your codebase, and readable stream 4. K? And when I will ship 5, you likely have 5 we'll have 5. Okay? That's what it is.
Matteo Collina [01:06:46]:
Okay? So there is there are some modules that get a lot of that are in a lot of dependency chain because typically for the typical historic reason. And at that point in time, it's, they were useful, but now probably way less so. So maybe you should stop using readable dash stream and maybe start using, you know, no no j the node just the node stream module because that's all of it. But, however, there's a lot of things where you still want to use that module, and therefore, here we are. Okay?
Dan Shappir [01:07:23]:
So so you made actually two points here, I think. First of all, you're saying node itself is advancing, and it's offering many built in features that in the past did not exist, that in the past we would have needed to bring in, like, 3rd party libraries. Now there are built in features in in the platform. And as with the browser, whenever I can leverage an existing part of the platform rather than bringing in a dependency, it's it's almost always a good idea. It's going to be a stable API, a well tested service API. It's gonna be there forever. I don't need to worry about maintainability, about security, about who gets ownership of it and starts pushing malware into it or or or whatever, and it's probably going to perform better and and so many advantages. So that's an obvious, thing.
Dan Shappir [01:08:22]:
But the other point you're saying is that I should be wary of having multiple versions of the same package running within my single node instance. Now I understand why it's a bad thing on the browser side because I've actually seen a browser based application deliver 3 different versions of Moment JS, which resulted in, like, a huge download, which is a problem on the client. Why is it a problem in my node server though?
Matteo Collina [01:08:58]:
The first problem is, related to your surface attack. Okay? The more dependency you have, the more you are exposed to potential attack. You want to have, genetically, the dependency that you need and only the dependency that you need in your tree. Okay? So this is the first point. Okay? Which, you know, each one is a vector is a potential attack vector. So you need to treat them like that. K? And the other stuff is it increases significantly the install time of the application. So if you do and increases, I don't know, CI time.
Matteo Collina [01:09:36]:
K? Just a tiny bit. K? But then another app can have easily 3, 4000 dependencies once all said and done. And then you start seeing, oh, okay. Can I just maybe remove a 1,000 of those? K? Each one of them needs to be downloaded in in the Just
Dan Shappir [01:09:55]:
a 1,000.
Matteo Collina [01:09:56]:
You know? I'm just, like, a lot of them like, there are some of them that are trivial. Okay? And, frankly, they should, you know, not be mobilized, but there we are. And some of them, they are
James Snell [01:10:11]:
need to be down leveled. Right? I mean, they just people just don't update their dependencies when they can, and so some of them end up just being brought in just because somebody decided not to update.
Dan Shappir [01:10:25]:
It's it's also the fact that it's like it's like like this sort of a skeleton. Like, the hip bone like, how that song go? The hip bone's connected to the thigh bone and so forth. So you bring in one note package, and that brings in 2 more, which bring in 8 more, which bring in 16 more. And and all of a sudden, you have, like, the entire universe downloaded into your, node instance, and you you did put that comic strip in your article about how the NPM modules folder is heavier than a black hole. How how do how do I contend with that? You know, if
Michael Dawson [01:11:03]:
I I I think the principle was about, like, be more intentional about that. If you're gonna you can easily pull in a packet and you're using some small part of that package And but take you should take a look at, like, what all did that pull in? If that pulled in a 100 other packages and you've effectively replaced 10 lines of code that you might have written yourself, maybe you should just put the 10 lines of code in. Right? So, you know, as Matteo said, the reuse is one of the fast, fantastic things about the the ecosystem. It's really easy to pull in code and reuse it. That's great. But I think we could use a little bit of a shift towards being a little bit more intentional in in looking at what you're pulling in versus the benefit you get, so that you're you're sort of doing the right balance between, hey. I'm reusing code easily versus the sort of risk that I'm taking on because, you know, I've got a huge amount of code. It's not just the attack factor.
Michael Dawson [01:11:59]:
What if there's a bug you wanna have fixed? You know, are you able to do that yourself? If not, that's something you should probably at least think a little bit about.
Dan Shappir [01:12:09]:
Yeah. Maybe you don't actually need left pad.
Michael Dawson [01:12:13]:
Right. Like yeah. You know?
Dan Shappir [01:12:17]:
Yeah. The the the sad thing is that, given the average, experience of developers, there's a good chance that half our listeners don't even get that joke about left pad because they came into the industry after it happened. Yeah.
AJ O'Neil [01:12:33]:
Well, the question is, are they still using it today?
Dan Shappir [01:12:36]:
There's a good chance that they are, though, but they probably don't know it because they're probably you not using it directly. They're probably using something that uses something which uses left bad.
AJ O'Neil [01:12:46]:
I think we need an ethos change to be more like Go and Zig and other sane languages. Make the standard library great again, And get rid of all the crap dependencies that I mean, there's so many, even security, dependencies where the people who are doing it obviously don't know what they're doing. You can't blame them because no one who did know what they were doing was doing it. Right? But I remember one of the early, very, very popular OTP libraries was, atrocious. You know, like, there's there's there in in our industry, I think because of there being so much money available, and thank goodness there isn't now, I actually think I I hope that the interest rates stay high. I hope they don't go down for the sake of our industry. For the sake of, you know, lots of other things, maybe. I don't know.
AJ O'Neil [01:13:37]:
But our industry was ruined by low interest rates. Because with free money, there was no responsibility to a customer, and then there was no there was no craftsmanship. And and then it became it became an ego thing. Like, look. I don't know what I'm doing, and I'm getting so much done anyway. Look. I don't understand how this framework works. I don't understand how the library works, but look how great I am anyway.
AJ O'Neil [01:14:04]:
And we need some sort of an ethos change to, like, hey. I'm able to do this with just a standard library. Isn't that pretty cool? Hey. I I'm able to understand how my code works. Hey. I I've got a handle on what my application is doing. Because if we don't have that ethos shift, then we're we're gonna get stuck in this the same rut that we're in. I mean, like, we're not gonna leave the rut.
AJ O'Neil [01:14:25]:
We're already stuck in the rut. We're not gonna get out of it.
Michael Dawson [01:14:28]:
No.
Dan Shappir [01:14:28]:
So an interesting thing that I have to mention. So a few episodes back, we've had we had Ryan, Dahl as a guest to talk about the dino 2 when it came out. Now interestingly, when dino itself first came out, dino 1, one of the things about it was that they avoided NPM and did try to provide, like, their own more significant built in standard library. And the thing about d n o 2 is that they well, surprise, surprise, they now support NPM because it turns out that without supporting NPM, you can't really
AJ O'Neil [01:15:03]:
get enough investment.
Dan Shappir [01:15:04]:
Well, not that. You can't really build practical things, especially for the enterprise.
James Snell [01:15:09]:
Users want you just wanna use users want to reuse NPM modules. I mean, that's all it is. I mean, so that that that that the whole joke about NPM being this black hole, that's exactly it. It's got such a massive gravity in the ecosystem that you cannot avoid it. Right? And and
AJ O'Neil [01:15:26]:
Right. But I don't I don't say I'm not gonna go use go because I don't have NPM, or I'm not gonna use Rust because I don't have NPM. Right? I mean, when you create something new, when you create something that's fundamentally different, you have the liberty to not take the baggage, you know, from from prior years. Like, you don't you don't use c and and well, in in some rare cases, you use c and go, like SQLite or something like that.
Matteo Collina [01:15:51]:
But, you
AJ O'Neil [01:15:51]:
know, in other languages, they're not they're not afraid to say, hey. One of the reasons we're creating a new language and a new platform is because we want to leave the crap behind. We don't want the crap to come with us. I'm not convinced. Sad that Dino conceded on that point.
Michael Dawson [01:16:05]:
I'm not convinced the other languages have have totally have necessarily done better. They may be in a different point on their journey. Like, I know in Go, I'm I'm I'm working on build packs for Node. Js. They're written in Go. That's the place we actually have, like, a dependencies that's deleted that's preventing things from being updated. And so, like, you know, NPM has gone through a fairly long learning process, and some of these other languages, like, it'll be interesting to see if they end up in the same place or, you know, they just haven't hit some of the challenges that you get with the scale that notice gotten to you yet.
Dan Shappir [01:16:42]:
I'm trying to remember who said it. It might have been c o. I don't re I don't remember. But, basically, they said that without NPM, we wouldn't have had caught. So so even even though even though NPM is not perfect, it's the most used, and that definitely says something.
AJ O'Neil [01:17:04]:
Yes. Though I am sad for for Metaverse. I am sad that they based cargo around NPM because it shows, and it's got a lot of the same problems. Whereas the Go package manager is empirically as perfect as it can be, meaning that it has the fewest trade offs. And you can prove that mathematically looking at the graphs, and there's a path where that's been done. So that that is really sad that we actually have something that we know both mathematically and practically works out, and we still choose other things.
Matteo Collina [01:17:32]:
Well, they was not there. Like, the go back
AJ O'Neil [01:17:35]:
to management I know. Yeah. For MPM, I know. But I'm saying cargo. But, like, it's it's sad that the I don't think it was
Matteo Collina [01:17:42]:
not there. Sorry. It was not there. I think it cargo predates the go back to manager.
AJ O'Neil [01:17:46]:
I'm pretty sure.
Dan Shappir [01:17:47]:
Yeah. Yeah.
Matteo Collina [01:17:48]:
Alright. I I guess came out very, very, very late in the game. For a long time, go was, in fact, the original d n o one, package package management, we came out from dino from Go. And they just say, well, you point us you point it to a URL and then you download it and they it it handle it. It handles it. Okay? Which is what's essentially our dependency we're managing Go, prior to that.
AJ O'Neil [01:18:20]:
Okay. Or, yeah. Yeah. Yeah. For the mono repos. Yeah. That that that is definitely yeah. Okay.
AJ O'Neil [01:18:25]:
I see what you said. Yeah. Because the it came out in 2018, and then it was and it was confirmed final in 2019, which it seems that's more recent than what it seems like. It seems like it was a longer time ago, but then, I guess, Rust wasn't really even hitting popularity until after 2018. So when I think about it, I I my memory is wrong. My memory is corrupt. I'm faulty. My bad.
Matteo Collina [01:18:51]:
But, yeah, I mean, you know, going back to
James Snell [01:18:53]:
some of, you know, the kind of the original thing with dependency creep and everything else. So, npm, like I said, it has this massive gravity, and if folks are using those modules, they want to keep using them. Unfortunately, there's just so many modules on there that they don't need to use. My my economical example, if you go out there and I and I don't wanna, like, pick on it too much, but there's a module out there called is even. All it does But
AJ O'Neil [01:19:17]:
that's that's parity.
James Snell [01:19:18]:
That's a joke. It it doesn't matter. I've seen people use it. It doesn't matter if it's a joke because peep I've actually seen people use this in their code.
AJ O'Neil [01:19:27]:
Like, not not a joke? They Yes. They used it as not a joke.
James Snell [01:19:32]:
Yes. Like because it was there.
AJ O'Neil [01:19:36]:
That's scary.
James Snell [01:19:37]:
It it is scary. But I I you know, my the first time I I found the isn't even module, which all it does is to is, pull in the is odd module and and negate it.
AJ O'Neil [01:19:50]:
And that that, like, has a list of a million numbers. Right? Or something like that? It's it's not even something simple like doing mod? No. No. Because I know one of the parity modules just has a list of numbers, like, 1 to a1000000, and then for every other one returns true? Okay. So it's not that bad.
James Snell [01:20:08]:
No. This actually does work. You know? And and and we'll check to see if the the data of the input is a number and, you know, and and that kind of thing that is odd. But all is even does is pull that in and negate it. I've seen you know, there there are a ton of modules on NPM that, like, you just don't need, and people pull them in anyway because they're not thinking about it. They're not being intentional about it, going back to Michael's earlier point, Or they don't understand what the module is actually doing. Right? And that's what they need to be focusing on. Goes back to same thing with with problem.
James Snell [01:20:43]:
I have a problem with about what you're doing.
Dan Shappir [01:20:45]:
I have a problem with that statement because to a great extent, the whole idea if of reuse is that I don't need to think about the implementation details. I can basically just look at the API surface and be content with that. If I assume if I can assume, let's call it, a good a good actor. If if I'm starting if I'm if I need to start looking under the hood of every NPM module that I'm using, why am I even using these modules?
James Snell [01:21:25]:
It comes back to the, you know, being intentional about it. Right? And I to some extent, yeah. But you have to understand there's a trade off. If you don't understand, you know, what the module is doing, it might be doing something incredibly, you know, performance, you know, costly. And yet and suddenly your application is slowing down. You go into production. Why is it slowing down? Well, when, you know, Matteo and I, countless, countless of consulting, jobs, we went out and found, hey. It's your dependencies that are slowing you down because they're just not, you know, written to be, very, performant in any way.
James Snell [01:21:59]:
And folks, well, we didn't know that. If we had known that, we wouldn't have used it. Well, you know, do some digging. You know, look at what your dependencies are doing. You know, it it you have to be aware of the COVID-nineteen pandemic.
AJ O'Neil [01:22:15]:
A good metric. Because I I think that with rails and I don't think that this necessarily was what the rails community intended, but it, bad pun. You know, the idea went off the rails. The dry. Right? Don't repeat yourself became it became a sacred cow that people didn't understand, and they just started to say it without knowing what they were saying or what it was supposed to mean. And this don't repeat yourself became this, you know, this this religious, fervor. And I I think a good metric would be would does the number of letters you have to type to search for it or or or query for it exceed the number of characters you would have to type in order to implement it? Because if so, you're on the wrong track. You should just copy and paste that code or type it out again.
Dan Shappir [01:23:11]:
It'll be interesting to see if, AI code generators make a dent in this. If people can instead of pulling an and and if they actually make an improvement also, if somebody instead of, pulling in a module that's does something can still, like, chat GPT or Copilot or whatever, write me code that does that thing and then copy paste it into into their code. Is that better or worse?
AJ O'Neil [01:23:39]:
I have had great success with ChatGPT writing far better code than what exists in the ecosystem that I could find. And I'm not just looking at modules that have the 1500 plus stars. I'll look for things that have 10 or no stars. I'm just looking for the best code that's available, and I'll go peek at the source code. 22 things that come to mind. 1 was shot 256. There because web crypto has shot 256, but it's really, really slow because of the context switches and the async. So if you need shot 256 for anything more than a one off, I would not recommend using web crypto.
AJ O'Neil [01:24:16]:
So all these modules on npm that have shot 256, they're all really legacy. They're you know, some of them are using a transpiled buffer implementation from Node. Like, none of them are using u
Matteo Collina [01:24:27]:
n
AJ O'Neil [01:24:27]:
8 array and modern JavaScript. They're all, like, decrepitly old. And I asked GPT to write me from scratch a SHA 256, and I was so skeptical. I spent 2 hours testing it, pulling from other libraries, like, grabbing their tests and bringing that in. Because I thought there's no way that it that it created a better library than anything that exists on npm in a in a one shot. But it is a really well known algorithm. There's lots of training data and lots of languages, and GPT does kind of tend towards simplicity. It doesn't have a context window to be able to create 7 different class hierarchies to do something.
AJ O'Neil [01:25:05]:
It kinda has to be able to do it in a function or 2, which I think, you know, also speaks to the the greater average of the human consciousness. Humans are not really good at holding 7 different class hierarchies in their context windows. Although, they they like to think that they do. But in some ways, I think that GPT is more truthfully reflecting reality than people are perceiving it. Another instance was a CBOR parser. And, you know, CBOR is something there's not very many implementations of it. But the implementations that exist, outside of JavaScript are extremely high quality. And so it was able to write me a CBOR parser in a one shot other than I had to make a a follow-up prompt because there was one function that didn't fit in it I guess, didn't fit in its context window.
AJ O'Neil [01:25:54]:
So I had this I could tell that it didn't have, one of the functions was missing. And so I said, hey. You're missing this. And I took that, and it worked. And so it at least in JavaScript, I can tell that and and part of it has to do with my memories because in GPT, I've told it, hey. Remember that I prefer this style. Remember that I prefer this style. So I I have also prompted it to to be simpler in the way that it writes code.
AJ O'Neil [01:26:20]:
But it was able to one shot 2 complex things that, you know, certainly nobody could write in 30 seconds. And very few people could write and feel confident that they wrote it correctly. And, you know, I was able to test it and and see that it did work. So but I think it takes the senior mindset to do that in the first place because you have to be looking for, hey. I looked at the code of this shot 256 implementation on npm, and it's absolute garbage. Not necessarily because it was always garbage, but be but but sometimes just because, like, it's got browserified translations, which, hey. Back in, you know, 2010, that's that was what you had to do.
Dan Shappir [01:26:59]:
That was I don't think it's the senior mindset. I'm looking at my kids, and, you know, they're getting into dev, and they make significant use of those AI tools. So I definitely think that there's a possibility that AI tools may reduce the amount of packages that we import because they'll they'll write those one shot type codes for us that that we often need instead of, you know, importing a
Matteo Collina [01:27:27]:
And then what will happen is that a box will spread everywhere.
AJ O'Neil [01:27:34]:
Yeah. That's the thing. It's that's why I said it takes the senior mindset because you have to know to test it. You have to know to determine if it's slop or if it's real. Because depending on the day, you know, when they update to a new model or, you know, do the revisions, I'll I'll have a day where I'm coding with GPT 4.0, and, you know, it's just like banger after banger. And I'm like, wow. And then a day or 2 later, I'll be asking it questions that might even be simpler or whatever, and it'll turn out just absolute crap. And it's like, okay.
AJ O'Neil [01:28:02]:
I gotta write this myself.
Michael Dawson [01:28:05]:
I I think that that's actually another aspect of of the reuse is that, like, if you're if you're your own person, like, if I'm just writing code for myself, I don't mind writing some new stuff and using that because, like, I'm the one who's gonna have to maintain it. If you're working in a company, I don't really you know, if I ran a a large company, I wouldn't want a 100 copies of the same thing written by 10 different people even if they're using AI to do it more quickly because there's gonna be different bugs, there's gonna be more investigation. So part of the the sort of the reuse is being intentional about what we what you reuse. And when you do reuse things, like, the great thing in the JavaScript ecosystem is we have tons of choice. The challenge is that we have tons of choice. So at least, like, within an organization, you should try and rein in that choice a little bit and say, well, okay. We're gonna use one version of x. Like, let's not pick 10 different ones because now we've just increased our surface area and our risks by 10 times.
Michael Dawson [01:29:03]:
We're gonna pick 1. We're gonna reuse it. And, you know, that's one way of continuing to maximize the value you get through use, but, you know, being intentional about the dependencies you have in your application. And as an organization, managing the risk so that you get a good balance between benefits or reuse versus the code you've got in your code base?
James Snell [01:29:24]:
If we bring it if we bring it back to the pillars, you know, if you look at every single one of those pillars, a key ingredient in every single one of those is intentionality. Right? It's, you know, get you to stop and think about your code, in some aspect of it. You know, what are you testing? What dependencies are you using? Right? How are your tasks broken down? Right? All of it is just about this this notion of being very, very intentional about what you're doing with your application. Dependencies are no different. Don't just pick a dependency because it exists. Pick a dependency because it does what you need it to do the way you need it to do it. Right? And and you know and understand what it's doing. Yeah.
James Snell [01:30:07]:
And it and it doesn't matter. If you're having AI write your code, it's the same thing. Right? You have to be very intentional about it, about about what you're trying to accomplish.
Matteo Collina [01:30:16]:
Guys, I need to drop. Unfortunately, it's about time for me. So I just want to say thank you very much for for joining. I for time, I would stay longer, but at this point, I really need to drop.
Dan Shappir [01:30:28]:
Okay? Thank you very much for coming on. We will I you're going to be a guest on our show to talk about something else in any event pretty soon, so we'll see you then. So thank you on thank you very much for coming on today. And I'm going to push us the rest of us into PIX anyway. We will just have to bring you invite you over to talk more about the pillars because we literally made it halfway. We made it into the middle of pillar number 5. So now we have the rest of pillar number 5 and then 6 through 9, and this is such a great conversation. I'm I'm so happy that it's turning out this way.
Dan Shappir [01:31:02]:
So thank you, Matteo, and, and see you in a bit in, like, a few more in a few weeks.
Matteo Collina [01:31:09]:
Bye. Bye. Bye. Bye.
James Snell [01:31:10]:
Same with you. Bye.
Dan Shappir [01:31:15]:
And you guys so, again, I'm gonna push us to PIX. AJ, do you wanna go first?
AJ O'Neil [01:31:22]:
Sure. I've got a couple. So I'll go ahead and throw out my link to the SHA 256 implementation. If you have an application where you need to be doing multiple shaas in a row, this this is the best implementation that exists in JavaScript. At least, there might be one that's just as good, but I was not able to find it. So I had to to publish this. This the and and it has been tested, extensively. So I, I am very, you know, I I dollars are on the line with it.
AJ O'Neil [01:32:00]:
But, anyway, so I'll I'll do that just as a a self promo since I since I talked about it. Because yeah. If web crypto works, because you only need to do 1 or 2, that's great. But the other the legacy modules that are out there, I just I would not recommend them because they're they're doing all this weird Browserify stuff or, like yeah. It's just they're just they're old. They're old. They're dated. They need to be replaced.
AJ O'Neil [01:32:24]:
And, Yeah. So go put the first star on there if you want to. And then I another thing I'm gonna pick, we're heading into winter. So we're we're in this season right here where I am of of nearly perfect temperature, which, the the weather's been really odd this year, and the the cycle of it's been kinda strange. But the last week or 2 has been pretty perfect temperature. We're heading into the thirties this week. So, it it it's and below freezing even. So that's that as soon as it came, it's over.
AJ O'Neil [01:32:58]:
That's that's how Utah is. It's like your spring and your fall are very, very narrow bands. Like, even 2 weeks ago, it was up in the eighties. This week, it's down in the thirties. So that's how it goes. But with it becoming winter, static shock is a thing. At least for us here in this dry climate. And a buddy of mine introduced me to these grounding mats, and they sell them as kind of woo woo, hocus pocus, like, it's gonna alleviate your back play pain problems while you sleep or cure your depression, which I don't believe that a grounding mat is gonna do any of that.
AJ O'Neil [01:33:36]:
If you do believe that, I'd be curious to know why. But I and, honestly, I I actually would be curious to know why if there's is there some sort of science behind it or some sort of, like, actual, what what it what it lived experiences or whatever. But but I get I got them. And I've got one for my feet and one for my hands Just because I I started to develop this fear of, like, touching the keyboard. Because every time I did I mean, it was it was a heavy shock. It wasn't just like a little, like, oh, I you know, I touched your sweater. It would really build up. And so I got these grounding mats so that I don't shock things.
AJ O'Neil [01:34:15]:
Also, real story about electric shock. I took my home network down, for 2 days. And I kept on unplugging things and replugging them, and then it would work for another hour, and it would go down again. It turned out there was a network switch that was connected to my desk. And I believe that what had happened was that I had inadvertently touched the one of the cables that went to the network switch. It had gotten into a bad state where it was just spitting out some sort of packet. I I I honestly believe it was from static shock. Because I had unplugged a bunch of other things, but I'd missed that one switch.
AJ O'Neil [01:34:56]:
And when I finally found that that, oh, I I haven't actually power cycled this thing like I thought I had. I think I had power cycled it, but it had a USB connection. So it would still add power, like, re from the USB or or something like that. But, anyway, I unplugged it, replugged it, and then I didn't have those network problems anymore. Very, very weird situation. But I think just getting shocked flipped a bit. So it also could potentially protect your, your electronics from malfunction having one of these, grounding pads. So I linked to one that actually feels nice.
AJ O'Neil [01:35:30]:
It doesn't it doesn't feel cheap and junky. It it has, it it feels like real leather. I don't know if it is, but it it feels like real leather. And it's very, very effective in terms of, if I'm using it, I'm not constantly shocking everything on my desk. If I'm not using it or I walk away on the other side of the room and come back, then I, you know, I put my hand down, and, of course, I shock myself. Anyway, grounding mats. Who knew? Who knew that could be a pick? But it is. And, that's that's what I got for y'all today.
Dan Shappir [01:36:03]:
Excellent. So now I'll go with my picks. I actually have 2 picks. So the my first pick is we watched on Netflix the, limited series called monsters, the Lyle and Eric Menendez story. This is a pretty famous and pretty gruesome story from, the end of the eighties. I think it happened. The actual event happened in 1981 about these 2 brothers that basically executed their parents, and, they were caught. They went on they went to a trial.
Dan Shappir [01:36:35]:
I won't spoil the rest of the story. There's actually three way the funny thing is that there are actually three ways to watch it on Netflix. There's the, limited series, which is a dramatization of the story. There's, a documentary series, and then there's a documentary movie. We watched the series and enjoyed it very much, and that's the thing that I would recommend the most. It's well played, well written. It's it's just it's just good pretty good television. Afterwards, we tried to watch a documentary series because we were kind of interested in the story, but it I don't know.
Dan Shappir [01:37:19]:
It just went into way too many details for us. So instead, we watched the documentary movie, which was interesting in the context of the series we just watched. But, again, if you're gonna watch something and just the one thing, do just watch the, limited series. Again, it's called Monsters, the Lyle and Eric Mineta story, and it's it's, it's a pretty good story. The one thing interesting about it is that recently, I think the governor of California, I believe, said that he's reviewing their sentences because and people are saying that it's potentially because of the stories that came out due to these, all these shows and all the discussion about them, which is kind of interesting how art impacts life, I I guess, in a sense. Anyway, so that's my first pick. My second pick is, things have been it's kind of people have stopped talking about it maybe because of the elections in the US or maybe people just moved on, but there was a whole lot of craziness around WordPress. Like, it kinda seemed like, the guy who's running automatic, who is like the, what's it called what's it called, the benevolent dictator of WordPress, which is Matt Mullenweg, I think his name is pronounced, seemed to kind of went off the rails.
Dan Shappir [01:38:42]:
I won't go into the entire story. It's it's pretty out there. Lot of crazy things happened. And if you are curious about what actually went down and and what's potentially still going on, the one video that I would recommend to learn everything about it, at least everything as was, as of about 2 weeks ago, is a a video made by, Theo, also known as Theo 3gg. It's actually in his Throwaways channel. We'll post a link. He actually spoke with Dan Saltman, another podcaster streamer, a bit less technical, and explained to him his the whole thing. And Theo was kind of involved in it because he actually spoke and interviewed Matt, and in and to the extent that his videos became part of the depositions in the ongoing lawsuit that's related to this whole story.
Dan Shappir [01:39:44]:
So, again, if you're interested in this craziness and wackiness in the open source world and where open source can go in bad situations, then it's a pretty interesting video to watch, and I and I recommend watching it. So these are my 2 picks for today, and I'll and I'll post the link to the links to both of them. How about you, James? Do you have any picks for us?
Matteo Collina [01:40:12]:
Let's see. Well, first
James Snell [01:40:13]:
of all, I'm I'm sorry if I get any audio. My earbuds just died, so I'm on laptop speakers now. So there might be some echo. So I apologize for that. Let's see. Fix for for today. Next week, we got NodeConf EU happening in in Ireland. It's always my favorite time of the year getting back, getting back to Ireland.
James Snell [01:40:36]:
We're actually returning to Waterford Castle. It's a the the conference is an actual castle. You know? It's just an absolute wonder fantastic, venue. There's still some tickets available. It you know, I know folks from the US. It's maybe a little little harder to get over there, that you know, last minute, but if you're over there in Europe and you have the time available, it's absolutely fantastic conference. Gonna be talking about, cross run time compatibility. So all this effort, like, Deno to act like Node.
James Snell [01:41:10]:
Bun working back like Node. Workers is trying to act like Node. How do we ensure that the all these different run times work the same when it comes to, like, you know, standard web APIs, that kind of thing? So we're gonna be talking through a lot of the challenges that, that all these different run times have, to actually make sure that they're compatible, with a language like JavaScript that allows you to basically do whatever you want. So that'll be that'll be a fun talk. But the other other side of it, and this is just my personal side, my son is going, my son has has been a contributor to Node for a couple of years. He's doing his own talk there with, with with another person, Claudio. And we're talking about the work that they've been doing to improve Node, release downloads based on Cloudflare r 2, and some of the other some of the other work that they've been they've been working on. So, if you have time, go.
James Snell [01:42:01]:
We'd love to to to to meet folks there, and that's
Dan Shappir [01:42:05]:
The family that notes together stays together.
Michael Dawson [01:42:09]:
Oh, yeah.
Dan Shappir [01:42:11]:
Cool. And how about you, Michael?
Michael Dawson [01:42:13]:
Yeah. I'll I'll my first one, I'll just agree with James. No cuff you next week is gonna be fantastic. The other thing I've been doing lately is spending time, like, learning a little bit more about AI, trying to use the libraries from JavaScript. And the the great thing is often, like, JavaScript or TypeScript is the second language supported. So if you look at a LAMA, a Lamedx, Langchain, which are all leading libraries in in the AI space, They they obviously all start with Python because really data science came out of that that sort of space, and that's the language they use. But most of the the leading libraries also then support TypeScript as their second language. And I think that that shows a recognition of the AI ecosystem that, like, JavaScript and TypeScript is gonna be an important player in terms of consuming those services.
Michael Dawson [01:42:59]:
In terms of my pick, I've been looking at this week, it's the b agent framework. It's actually one which started life as TypeScript instead of Python, which is nice to see as a node developer that somebody started with a a JavaScript implementation. It lets you write agents that call functions, more easily. So I've been playing around with that. And if you're interested in, you know, node and and consuming AI from JavaScript, TypeScript, I I throw that over as my pick to go take a look at that.
Dan Shappir [01:43:28]:
Very cool. Now before we wrap up, if people want to get in touch with you guys to talk about what we talked about today, I don't know if you still do consulting work or in general just to speak with you. How do they get in touch, Michael? What's the best way to contact you?
Michael Dawson [01:43:42]:
I think, you know, Twitter, my handle's there, mhthawsonone. You can just reach out to me through that.
Dan Shappir [01:43:48]:
Excellent. And how about you, James?
James Snell [01:43:50]:
Same, on Twitter. I'm j a Snell, on Twitter and on GitHub. I I think we have to be following each other for you to DM, DM me, but, you know, feel free to reach out. Do a public chat out on me on on our happy chat.
Dan Shappir [01:44:07]:
Excellent. So, guys, it's it was great having you on, and I'm I really hope we can organize and schedule the follow-up because we do really need to cover the rest of the pillars. The ones that we did were so great. Thank you for coming on. And to all our listeners, thank you for listening in, and goodbye.
Structuring Node.js Applications: Event Loop, Metrics, and Efficient Processing Techniques - JSJ 657
0:00
Playback Speed: