Structuring Node.js Applications Part 2: Dependency Management, Package Managers, Proper API Usage, etc.- JSJ 661

This is the second part of the deep dive into the essential practices and principles for successful Node.js development. Our esteemed guests, Michael Dawson, James Snell, Matteo Collina, and Natalia Venditto, bring their extensive expertise to the table, discussing key topics like how to manage dependencies in a Node.js project.

Show Notes

This is the second part of the deep dive into the essential practices and principles for successful Node.js development. Our esteemed guests, Michael Dawson, James Snell, Matteo Collina, and Natalia Venditto, bring their extensive expertise to the table, discussing key topics like how to manage dependencies in a Node.js project.

Socials


Picks

 

Transcript

Charles Max Wood [00:00:05]:
Hey, folks. Welcome back to another JavaScript Jabber. This week on our panel, we have Dan Shapiro.

Dan Shappir [00:00:11]:
Hello from what we in Tel Aviv like to call winter.

Charles Max Wood [00:00:16]:
Well, I wish our winters were that warm. I'm Charles Max Wood from Top End Devs, where I think you got below freezing last night. That 0 if you're not in the US and you something other than Fahrenheit, and that's, like, 32 degrees Fahrenheit. So got real cold last night. This week, we're

Michael Dawson [00:00:36]:
following up on the 9 node pillars episode that came out a few

Charles Max Wood [00:00:39]:
weeks ago or a month ago. So we've got, some familiar faces, but we'll go ahead and let them introduce themselves again. I'm just gonna start at the top of my screen, and we'll just kinda work our way down. We have Michael Dawson. Michael, do you wanna introduce yourself?

Michael Dawson [00:00:54]:
Hi. Michael Dawson. I'm the Node. Js lead for RadHat and IBM, as well as active in the project on the technical steering committee, and live definitely where it is getting below 0 at 19.

Charles Max Wood [00:01:05]:
Right. Practically, neighbors. We also have Matteo Collina.

Michael Dawson [00:01:10]:
Hi, everyone. I'm Matteo Collina, platformatic cofounder and CTO, vice chair of the Net. Js technical steering committee, a board member of the Net. Js Foundation, author of many modules. You're probably using my software even if you don't even if you want or not. That's probably my tagline.

Charles Max Wood [00:01:28]:
Awesome. We also have James Snell.

James Snell [00:01:32]:
Yeah. Yeah. Yeah. James Snell coming from Central California. Where winter here means just slightly less sunshine than than than typical. I'm at Cloudflare. I work on their workers' runtime. I'm on the node technical steering committee.

James Snell [00:01:47]:
I've been contributing to node for, jeez, almost 10 years. I think in March, and in just a few months, I've been on the technical steering committee for node for 10 years, a whole decade, so we're just which is crazy. But, yeah, that's me.

Charles Max Wood [00:02:01]:
Awesome. And finally, we have Natalia Vendito.

Natalia Venditto [00:02:06]:
Yeah. Thank you for having me. I am the lead for developer, tools and experiences for JavaScript on Azure. And, yeah, also participating of the Open JS Foundation CVC. That's me.

Charles Max Wood [00:02:21]:
So, yeah, so last time you talked about the 9 node pillars. I think it's worth maybe a 5, 10 minute review, something like that, just kinda get people back into it. Obviously, folks can go back and listen to the other episode if they want the in-depth discussion, but then we get

Dan Shappir [00:02:37]:
They should. It was an excellent they definitely should. It was an excellent conversation. It's an excellent article, and it's an it was an excellent conversation in my opinion. Unbiased opinion.

Charles Max Wood [00:02:49]:
Well, my point is is then we can get on with the other, you know, 4 or 5 pillars. So really quickly, I'm just gonna pull them out of the article, and then if whoever wants to, you can kinda jump in and just kinda summarize what was discussed. The first one is do not block the event loop.

James Snell [00:03:11]:
Yeah. This one's pretty straightforward. You know, it's like, you know, you gotta keep in mind that anytime you're running some bit of JavaScript, you have some function, nothing else is gonna happen, on that event loop. So it's like you need to make sure you're dividing your work into to very small chunks, allow the event loop returns. You can pick up new requests. You can, process IO, that, that kind of thing. So pay attention, to, you know, that event loop delay, event loop utilization. There's a couple of metrics there you really wanna watch closely and optimize your applications around that.

Charles Max Wood [00:03:44]:
Yep.

Dan Shappir [00:03:45]:
And also offload, if you can, lengthy tasks to a worker if at all possible.

James Snell [00:03:51]:
Yep.

Charles Max Wood [00:03:51]:
And I'm assuming you talked about strategies on how to do that and what your code should look like in the other episode. So Yep. Yep. The the next one is monitor node specific metrics and act on them.

James Snell [00:04:04]:
Most

Michael Dawson [00:04:05]:
let me take this. Most of the things that people do when deploying Node JS is they monitor Node JS like it's, in a completely, like it's a black box. And this is a massive, it's a massive pain because you, because it's in a most cases, Node. Js has its own quirks and peculiarities and monitoring it like a sub black box. You are essentially making it a Unity service. Biggest one being memory. Node. Js will use as much memory as you make it available to it.

Michael Dawson [00:04:39]:
And if you start killing it when it reaches, whatever arbitrary threshold, you know, you're killing the process yourself and the and then restarting it and complaining that your process is crashing all the time. You're killing it. Of course, it's crashing all the time. Okay? It's literally like this thing alone is probably, I don't know, worth a few hours of of right time, super high end call. So this is for free. So, you know, take it take it the the way you want, but this is essentially, you know, very easy fix. But most people don't. Most people monitor our SaaS, micro CPU usage, but don't look into what's happening inside the process, and this is you know, makes all the difference.

James Snell [00:05:18]:
One of the key metrics there, that was added relatively recently is the event loop utilization. It's gonna tell you a whole lot more information than than than monitoring a CPU. Yeah.

Charles Max Wood [00:05:30]:
Awesome. The next one is use Node LTS, which is long term support versions in production.

Michael Dawson [00:05:38]:
I think that one is, like, you know, as a project, we we support the long term support streams and the recommendations really stick with those because in terms of security fixes and stuff like that, that's where you're gonna get those, and and most people do wanna update when they those commit.

Dan Shappir [00:05:54]:
And these are the even numbered versions. Right?

Michael Dawson [00:05:57]:
That's right. And they come out every October and are supported for 30 months.

Charles Max Wood [00:06:03]:
They usually say LTS. It's like it's the version number and then it says LTS. So if you have a question, just look for that and you'll know. I think we all kinda stared at each other on that one like it was pretty clear that that's a good move. The 4th one is automate testing, code review, and conformance as much as possible.

Michael Dawson [00:06:25]:
Yeah. That one I'll jump in. We talked about last time. I I think, like, Node. Js is known for being able to let you move really fast and be productive, but you need really good testing to be able to move quickly to make sure you're not gonna break things. So that's where we last time we talked about, like, how that how it is really your enabler to take advantage of the the sort of speed speed and agility that node gives you.

Dan Shappir [00:06:49]:
We also spoke about the fact that people still use old testing frameworks, which are showing their age, and that node now comes with its own built in testing framework that you can really easily leverage out of the box.

Charles Max Wood [00:07:06]:
Good deal. And then it sounded like you got partway into, but didn't completely discuss, avoid dependency creep.

Dan Shappir [00:07:18]:
Yes. We we spoke at length about how NPM is kind of like this black hole which sucks the entire universe into it. So you add one dependency which brings on another couple for the ride, which bring even more and more and more. And we talked about the fact that you need to really be, how would I say it, cognizant of what you're bringing in. It's, intentional, I think, was the term that we use. Think about what you're bringing in and why you actually need it, and if there are lighter weight alternatives, and beware utilizing multiple versions of of the same, library. Anything else we mentioned that I'm missing?

Michael Dawson [00:08:05]:
Yeah. I think the one one of the aspects was, like, within an organization, the great the good thing about NPM and all the choices there is there's lots of different choices. But, like, in an organization, it would make a lot of sense to choose a more standardized set of packages as opposed to having 5 copies of something which does the same thing, but are actually slightly different. Because when it comes to helping each other or to debug issues or to be able to support them, that can be an advantage. Of course, you you know, there's always cases where you wanna use something special to your particular effort, but, like, that's probably the 20% case versus the 80%.

Dan Shappir [00:08:42]:
By the way, with with regard to that, one thing that I thought of and I don't think I mentioned the last time we spoke about about this, is the fact that I know some organizations that intentionally take, call it micro front ends, microservices type approach of trying to create as much segregation as possible between various teams and reduce teams' dependencies on dependency on each other. And that means that, for example, one team might choose to use, one package or library, and another team should be free to choose something else and or that they don't need to move at the same rate with regard to versioning and and stuff like that. Now, obviously, if they if they go the old way or the whole way with with micro services, then they're probably also running separate node instances, which might reduce the impact. But they might be running within the same node instance, and then they're kind of working in contradiction to this recommendation.

Michael Dawson [00:09:48]:
I think, like, if you look at it, like, maybe that plays into not using like, not forcing people to be using the same version, but I still think even in that case, there's value to say, like, let's all choose the same logger. Right? Like, we don't need to use 10 different loggers. So, for example, if somebody moves from one team to the other, they they already know the logger and the patterns and so forth that are used. And breaking it up into microservices, like, that's sort of a different kind of dependency in my mind anyway.

Charles Max Wood [00:10:18]:
Yeah. I I agree. I've worked on a number of projects where we, you know, we try to segregate things out this way. And what I found is that sometimes there are good reasons for deviating from what the other teams are doing, and sometimes there really aren't. And so, a lot of this, you know, they try and segregate it so the teams don't have to spend as much time, you know, coming together and collaborating. But this is more of an organizational issue, I think, than than a code issue in the sense that you should still be talking, and you can still leverage the expertise of the other team where appropriate and say, alright. We've got to solve this problem. We know you have this same problem.

Charles Max Wood [00:10:57]:
What are you using? And then you can have the discussion about what and where and why. And then when we look at it from our problem perspective, right, because we're working on a different part of the app, then we may say, that all makes sense. And we tried to put it in, but it turned out these concerns lead us to a different solution. But then you have a good reason for saying this is why we're doing it different as opposed to the other thing. But it also then makes people more mobile between the teams. It makes it easier to talk about some of the similar issues. And so I think there's some nuance here, but I like the direction of saying, hey. At least consider what everybody else is doing in your organization.

Michael Dawson [00:11:36]:
Part of my part of the concerns here is you really want to to even say, okay. So we have created a way to a little, a module to call this microservice, okay, that is consumed by everybody. K? And I want to take that code and publish it on my internal, registry. Because, otherwise, each other team is going to redo it, and each other team is going to use a a different a p HTTP library for calling it, okay, which is bananas. K? I've seen this happening over and over again. Okay? Literally. Time wasted due to writing API clients. But now we have a a point there for top rating API clients, but this is essentially this is part of the problem.

Michael Dawson [00:12:29]:
This is one of the problems. Now this happens to all the things. Okay? It is, I need a library to validate that my custom field is correct. Right? And then I need this custom data. Well, let's put it somewhere so that I don't need to reimplement it all every every single time.

James Snell [00:12:51]:
So yeah. It comes down to being intentional. It it just comes down to being intentional. You need to be more intentional than you are opinionated. Like, you know, engineers are gonna have opinions on it. You know? I I I don't agree with doing it this way. I'm gonna write another library that does it a different way. And it's like, in an organization, that's just not gonna work.

James Snell [00:13:08]:
You can get so far with it, and it's just gonna cause more headaches in in in overhead. So do it once. Publish it for everyone you use. And you know what? If you don't agree with it a 100%, so what? Use it anyway.

Charles Max Wood [00:13:20]:
Yeah. As far

Natalia Venditto [00:13:21]:
as the integration between enterprise. Yeah.

Charles Max Wood [00:13:23]:
I agree. Go ahead, Natalia. Sorry.

Natalia Venditto [00:13:25]:
Yeah. Yeah. In enterprise development, I think many people forget there is this intermediate layer. Like, everybody can consume from upstream whatever module they want. But, again, like Mateo and James, stated, you need to be conscious of what you're building yourself and make it available to others. In the end, you have a smaller ecosystem with within your company, your organization that, allows you to publish to any private registry and also, function in the same way as open source, but within the boundaries of your organization. And by the way, this is definitely an organizational convenience, not not so much a technical one. I think in the front end, definitely try to keep dependencies that you're probably shipping over the wire to a minimum.

Natalia Venditto [00:14:18]:
But in the back end, what you want to do is to make sure that you have a lower maintenance, requirement than than when you have a a lot of modules to to maintain.

Dan Shappir [00:14:31]:
One thing that I encountered with organizations thinking about reusing their own components within the organization. So sometimes they're very explicit about it. So for example, if an organize in the context of front end development, an organization decides they're gonna have a, design system and they implement some sort of a front end library, that's pretty typical. But working in a in a, let's say, in a certain project and then coming to a conclusion, hey. This piece of code that I wrote seems to be something that will be generally useful across the entire organizations. People have that moment but are sometimes, hesitant to act on it because you're assuming a lot more responsibility than you originally had. Like, if you're just writing something for your own use within your own team, that's one thing. But committing to support every use case within the large organization, that's a different type level of commitment altogether.

Dan Shappir [00:15:34]:
And and making that jump can be, you know, significant.

Natalia Venditto [00:15:40]:
Yeah. I mean, if that's true, I have yeah. Sorry. Go ahead. Go ahead, Michael.

Michael Dawson [00:15:46]:
I said that seems to be the thing in life. The more you do, the more you pick up in terms of responsibility of keeping things going. So I could totally see people Yeah. Worrying about that.

Michael Dawson [00:15:56]:
Now I have a absolute counterargument to this. Okay? And, and I I want to flag out this functional and why you need to be intentional when creating this kind of software when when thinking about dependencies and software usability within your organization and enterprise, and also how enterprise absolutely sabotage themselves while doing so. Okay? So imagine that each team needs to, you know, implement a piece of functionality. Okay? Now one of the teams that they they discussed, one of the team is the first one, and they created their own little module to do this. And this is well. Here it is. I'm publishing it on my npm internal npm. Right? Great.

Michael Dawson [00:16:42]:
Everybody's happy. The management is very happy. We saved a bunch of money, so we need to can reuse all these things. Fantastic. K? Now, however, a a moment after that's happened, the team that created that module completely drops the ball on on on it because, nopes, it's not part of my OKR anymore. The quarter has changed, so I'm not maintaining this anymore. And this is the typical thing what happens with OKRs. Okay? If what you're doing is not part of of your OKR of of your, does not help you achieve your key results, you are absolute that thing needs to be dropped.

Michael Dawson [00:17:20]:
K? Even though it's important and, you know, you're saving the company lots of money by avoiding duplication. So, in reality, a lot of teams in some enterprise, works a little bit like silos, And they are A

Dan Shappir [00:17:34]:
little bit?

Michael Dawson [00:17:36]:
Yeah. Yeah. I I have yeah. I think Natalia has a few stories on on on that. So I don't know. It's, but Yeah.

Natalia Venditto [00:17:44]:
After a decade as a as an enterprise developer, I have many stories. Yes. There are silos. And I I do agree, Matteo, but but typically, enterprise projects do not work under KPIs. The KPIs is delivering your project. It's a little bit different than product. And another thing to your favor is that if you are building something that you publish to a private registry and you move to another project, which is usually the case of developers in in the context of enterprise, you are rotating. You're going to a different project.

Natalia Venditto [00:18:20]:
You can reuse it. Right? You have it pal you have it available to your new project. Whereas if it's part of a private code base, you don't have access to it anymore. Right?

James Snell [00:18:32]:
And and I think that there's I'm sorry sorry for the dogs here, but I think another aspect of this that was completely overlooked is a lot of times these internal teams will look at, hey. This other team created this this package that I wanna use. It's their responsibility to maintain it so I can get the benefit from it. That's entirely the wrong calculus. It's if if if Yeah. If I'm get up to use it in my project, I'm also picking up the burden to help maintain it. So, you know, we we can't have this idea that it's like, oh, that other team's responsible for it. No.

James Snell [00:19:05]:
No. No. All the same company. All the same team. It's it's equally my responsibility as anyone else's.

Michael Dawson [00:19:11]:
Let me

Dan Shappir [00:19:12]:
be blunt. If your assumption is that if you run into a problem because your needs change and the current and the package doesn't properly or adequately support it and you're dependent on somebody from some other team who, as we said, may have different OKRs, different priorities, you're literally screwed. I mean, you have to take the attitude and the approach that if you're using it, you're assuming responsibility for it.

Michael Dawson [00:19:40]:
That that can almost still be totally extended to every module you use from NPM because in that case, the people who who may be maintaining it are even further away from you and even have less reason to necessarily prioritize your Mhmm. Your requirements. So

James Snell [00:19:57]:
But the right. And and I I I'd a 100% agree with that. I mean, I I've said before many times where, you know, especially companies, if you are making use of open source, then you as a company have an obligation to help support that open source that you're that you're using.

Dan Shappir [00:20:11]:
Mhmm.

James Snell [00:20:11]:
And that includes contributing back bug fixes, changes, or whatever, and working with those maintainers. Don't put that burden on them, especially if you're not paying them.

Dan Shappir [00:20:22]:
By the way, an interesting aspect that I've seen is that at least for some organization, when when they decided to share some resource across the entire organization, it was actually easier from the organizational perspective to turn it into an actual open source project than to try to maintain it as an internally shared resource. Because once it was declared an actual open source project, it was actually allocated resources versus when it was just an internal thing that's shared, you know, ownership was

Charles Max Wood [00:21:01]:
meh. Yeah. One thing that I wanted to piggyback off of, what Mateo was talking about a little bit earlier is that and and this is coming from when I was working on integrations, and it was mostly third party integrations within, an application that I was helping maintain. But, also, you know, between microservices is that if you can structure your because he was saying, you know, if if you're writing the microservice, you ought to be writing the library that consumes it and giving everybody a standard way of of accessing it. And for me, if you can structure all of those the same way and make sure that they all kinda look and feel and are built in the same manner, again, it makes it easier for people across the organization to be able to come in and do that maintenance for you so that they can you know, you you can move ahead. So then it's, hey. This microservice has this feature that they built in, but they haven't updated the the library for it. Or maybe I need to make, pull the data in, but I need to do something a little bit different with it before I consume it in my service.

Charles Max Wood [00:22:07]:
You know, if it's all structured in a similar manner, then I know where to go to go ahead and add that in. And then everybody else benefits from it, and I don't have to go in and reverse engineer this driver or that driver or this integration library and that integration library.

Dan Shappir [00:22:22]:
I do I do want to I do want

James Snell [00:22:24]:
to sorry.

Dan Shappir [00:22:27]:
I do want to push us along a little bit because we are we are never gonna finish the pillars otherwise.

Charles Max Wood [00:22:32]:
I do

Dan Shappir [00:22:33]:
I do want I do

Michael Dawson [00:22:35]:
want to them today.

Dan Shappir [00:22:36]:
Yeah. I do want to touch on 2 things that were mentioned in the article in this context, at least briefly. One is that, node APIs versus web standard APIs, and the other, you also man mentioned, monorepos. So can you talk about can someone talk about the Node. Js standard native or standard APIs versus the web standard APIs?

James Snell [00:23:00]:
Yeah. I can definitely talk about that. You know, we have a number of places in Node now. You know, the old URL parse versus new URL, Node streams versus web streams, old Node crypto versus web crypto. We have a lot of these cases, where we have, you know, duplicate or overlapping APIs. And we talk you know, URL is the very first one that I introduced. And it there was this huge controversy even within the project. It was actually yelled at at a conference by another node contributor, Like, actually yelled at for suggesting that we add this, because URL parses there and and and it's fast.

James Snell [00:23:35]:
And, you know, when we added the new URL parser, the webwg URL parser, I mean, it was slower, but it was standard. And folks reuse libraries for a note you know, in Node and browsers, and and Dino picked it up. And that you know? And and suddenly you can use this thing everywhere. It's it's it's much more portable. Now it's faster than anything else. We're we're gonna see this pattern continue. And whenever you are whenever you're selecting which API to use, say, node streams versus web streams, be very intentional. Don't just make it an accidental choice.

James Snell [00:24:08]:
Be very intentional on how you adopt these. Node streams are gonna be way more performant than web streams, but web streams are way more portable. So you need to balance which, which goals you're looking for and make sure you're selecting your dependencies accordingly. The more you have to translate between them, like, say, if you're using both node streams and web streams, the more overhead and the easier it's gonna be to get it wrong. So you need to be very intentional about your strategy and which APIs you're picking. But something URL parse, just don't use it anymore. Use new URL. So

Michael Dawson [00:24:41]:
something important is Node. Js in general, okay, has added a lot of APIs in the last, decade. Okay? And most people still develop Node. Js like it's 2014. So please stop. K? Take a look at what's there. K? Like, literally oh, we have fetch now. I was I was checking recently, and we, and, you know, a few of the top downloaded modules on npm are high level, HTTP clients, and we had fetched for a while in node.

Michael Dawson [00:25:18]:
K? And you know?

James Snell [00:25:20]:
And even simpler, UUID. The UUID module, a lot a lot of folks you you know, pull it off of NPM, to just generate a random UUID. Great. It's a great module. But compared to the API that's built into Node and browsers, you know, we have web standard API, which is random UUID. It's on the crypto object. It's way faster, way simpler, and it's it's just the thing you should use. You could drop an entire dependency.

James Snell [00:25:47]:
That's been in there since, 2021, and folks are just now discovering that it that it exists in the wrong time.

Charles Max Wood [00:25:52]:
So I just wanna point out that Matteo pointed out that the node team made fetch happen, and so please stop trying to make fetch happen. K. Sorry.

Dan Shappir [00:26:06]:
We were actually just, I think, Matteo, we were exchanging tweets about it or exes about it, or or was it on on, Blue Sky? I don't remember anymore. So many options. And so that's number 1. So, basically, if I'm if I'm

Charles Max Wood [00:26:22]:
gonna I have a question here. Is there a good place to find these? Right? The hey. You might be using a library for this and you don't need to anymore?

Michael Dawson [00:26:31]:
No. Just to But, probably, it's probably something that we should develop and promote a little bit. Okay? Maybe, like, this can be a good a good a good something that's missing. I don't know. This is they are there.

James Snell [00:26:47]:
This is something this is something I would actually look, you know, Natalia, you know you know, for, like, dev tools or, like, the developer experiences like that. Because those of us that are actually working on the APIs suck at the documentation and actually promoting these things. But if we can start having leveraging the tooling to to, like, promote some of these things more and, like, say, hey. There's this other thing. It might be interesting, to to to look at that. We need to get better at this.

Dan Shappir [00:27:11]:
A certain way to go about it is to basically, if you're looking for certain functionality, check if there's a web API for it. Based and that's really easy because, for example, you have got MDN, and then just check if that also exists on node. That just that before you rush off and and and NPM install something.

Michael Dawson [00:27:33]:
One of the things we are doing in the project is we're ramping up some, ambassadors. And part of that, we're coming up with messages we want, those ambassadors to help promote. And that suggestion of, like, I think we've called it something like developing with modern Node. Js. Right? Like, to highlight here are the things that are available that might not have been available before is definitely on the list of things that are being brainstormed there.

Dan Shappir [00:27:58]:
Anybody wants to say anything about monorepos before we move on to the next one?

Michael Dawson [00:28:07]:
I'm just going to say use PMPM. This is my preference. Okay? I am personal this is my personal preference. Use npm when you don't need mono repos. Use npmpm when you need mono repos. This matches more or less my, yarn seems to work fine

Charles Max Wood [00:28:25]:
for other

Michael Dawson [00:28:26]:
people. But, genetically, my current status is I'm very happy with PMPM. I don't know. Natalia, you what you guys use? You you

Charles Max Wood [00:28:35]:
have a lot of Yeah.

Natalia Venditto [00:28:36]:
No. I I second yeah. I second that. I I use PMPM for mono repos right now and and PM for all the rest.

James Snell [00:28:47]:
Yeah. I'd have to agree. There's there's out of all of them, that's the one that handles this better. Their patterns are just they actually make sense.

Dan Shappir [00:28:57]:
So, Chuck, maybe move us along to the next one.

Charles Max Wood [00:28:59]:
I was gonna say, sounds like we've gotten that one. So the next one is derisk your dependencies.

Michael Dawson [00:29:09]:
I think it comes back to the the part we were talking about being intentional. Like, I think too many people pull in a very deep dependency tree without thinking about it, and and it's you know, once once you've you you pulled things in, then then we were we talked a little bit before, like, you almost need to take on the approach of, like, okay. I'm using this. Am I ready to help maintain it? Because, like, as an organization, not you know, James mentioned, like, you should do that because it's the right thing to do. But I also think as an organization, it's risk management. Right? In most organizations, that's a big part of them is, like, how do we manage our risk? And as soon as you fold in the software, it's part of the things you should be looking at in terms of managing your risk and saying, well, like, if we had to switch to something else, could we? If we had to make a change, could we? Is it a healthy project? And, you know, and and I think in in near the end there, we talk about, like, one way to manage your risk is to support the project either through your people or through funding. And, you know, so most organizations should should probably invest a little bit more time in managing that particular risk than they do.

Dan Shappir [00:30:20]:
Maybe if the maintainer gets enough support, he won't sell or he or she won't sell the project to some nefarious third party.

Michael Dawson [00:30:30]:
Well, that that's an extreme example of of the case. Right? Or they just might not have

Michael Dawson [00:30:36]:
So Node. Js ecosystem, unfortunately, has been full of those, okay, a couple of times already. So, unfortunately

James Snell [00:30:42]:
I mean, it doesn't even have to be sold. Right? If the maintainer runs out of time to get burnt out, they transition it to somebody without Yeah. You know, without fully vetting who they are. You know? Then somebody else can come in and take care of the project. You know? Like, take advantage of the project. Anytime you add a new dependency that you don't control or you're not contributing to, you're adding risk. You know? And and if you're if you're bringing in a module that brings in, you know, a 100 different dependencies, then you're increasing your risk a 100 full. So, you know, you just have to be very intentional about what you're bringing in.

James Snell [00:31:14]:
You have to be very intentional about what you're gonna support. And companies have to stop looking at open source as just free software that they don't have to do anything, with to to use. They have to help maintain it or they're bring or they're just opening themselves up to risk. And then if we look at, like, you know, some of the new, like, federal guidelines, you know, it's not just US, you know, EU as well, around SBOMs. The, you know, you know, actually being able to produce a, an audited list of these are the dependencies I'm using. Here's how they're maintained. Here's what the licenses are. A lot of folks bring in these dependencies without ever thinking about them.

James Snell [00:31:48]:
But as I said, if if your module ends up in some you know, being used in some regulated industry, you have to be able to account for those things, and and be able to account for the risk. So it's it's not just a a best practice. In some cases, it's an absolute requirement.

Dan Shappir [00:32:03]:
And there's tooling that can help you with this. Right?

Michael Dawson [00:32:06]:
Oh, yeah.

Charles Max Wood [00:32:06]:
I was gonna say because it's it's not just tooling, but it's tooling that you'll use. Right? And for me, it kinda has to be automatic and get in my face because I'm lazy, and I don't go look at it every however often you're supposed to. It's like changing my oil. Right? It's not till the light comes on and I go, You know?

Michael Dawson [00:32:26]:
Well, that's that's where I find it a bit surprising. Like, I don't know however often it is, but every so often, there's some high high profile case where it's the extreme. You know? The the maintainer goes off and does something to their module that they probably shouldn't have. But everybody seems surprised that this can happen. Right? And, like, if if you paid attention, it's sort of something you should know can happen and a plan. And so it shouldn't be a surprise, and everybody seems to get in a big fuss. And then after a few months, it tails off, and it's not in your you know, it's not in the news anymore, and people forget about it again.

James Snell [00:33:03]:
So I I find that interesting. Just anecdotally, I'm not I'm not gonna say, like, you know, who or what module it was, but, you know, this is going back in back to 2015, 2016, one of the most used modules on in on NPM. And the maintainer was quite upset and threatened to just delete everything. You know, delete everything off get up delete everything off NPM. And it came down within minutes that we were able to to convince them not to do that and would have broken the entire ecosystem, literally, had they had they had they done this. And, you you know, it it sometimes, it just comes down to a maintainer being burnt out and not feeling like they actually have the support. It doesn't have to be anything nefarious. It doesn't have to be selling it or somebody else taking over.

James Snell [00:33:44]:
It could just be kinda tired of dealing with this.

Dan Shappir [00:33:48]:
Yeah. It is important to mention, though, that following what happened with left pad, that specifically can no longer happen with NPM.

Charles Max Wood [00:33:56]:
Yeah. But, I mean, I can also see, you know because you guys have talked about, you know, you hand it off to a new maintainer or, you know, somebody otherwise takes it over. But I could see somebody just being tired and, you know, they they know they have a problem in their package and they know they want it fixed and they get a PR that looks like it solves it and it's got something problematic in it. I mean, you know, just that easy, you've got something in there that you don't want. Yeah.

Michael Dawson [00:34:22]:
I think back to Dan's comment, like, the I think that this has been a challenge or or a feature of the Node. Js ecosystem for quite a long time. So things have improved. Like, you know, the NPM, you can no longer delete things. And so a lot of that learning has actually helped to improve the ecosystem over time. Yep. That other other sort of language ecosystems may be relearning some of those lessons along the way. But

Charles Max Wood [00:34:47]:
So beyond sort of being aware. Right? Hey. There's an announcement. This package is gonna cause you this problem. Right? It's got, you know, somebody put a backdoor in it or, hey. We discovered a 0 day. Right? It doesn't even have to be that nefarious. Right? You know, the best practice has changed and they haven't kept up with it.

Charles Max Wood [00:35:05]:
Right? And so, you know, you just need to update it or whatever. Beyond that, I mean, I I know there's, like, NPM audit, but I kinda have to just run that on my machine when I'm running stuff. And, you know, sometimes I see the notifications, sometimes I don't. But are are there are there tools that while I'm working are going to tell me, hey. You have a problem. Like, I may not have seen the Twitter post or I may not have seen the blog post or the announcement or whatever that's gonna help me stay

Dan Shappir [00:35:33]:
up on this stuff.

Natalia Venditto [00:35:36]:
Dependabot is the first one. Right?

Charles Max Wood [00:35:39]:
Kind of

Natalia Venditto [00:35:39]:
a problem. You should be looking at, And it's going to automatically unless you disable it, but you shouldn't. I don't think that's something you should do.

James Snell [00:35:51]:
And I've that that's where when I've also become a been becoming a a a big fan of the socket the the new socket. Io stuff. So not socket. Io. I have process company.

Dan Shappir [00:36:05]:
It's socket.dev, I think. Yeah.

Charles Max Wood [00:36:07]:
We we had them on. I'll I'll find the episode number, and we can put it out there.

Michael Dawson [00:36:13]:
Yeah. I think the first part that Natalia mentioned is just keeping up to date, and there's tools that will basically like, those keep you help you keep up to date. And then there's other tools like the socket one or or who help look more specifically at, like,

Michael Dawson [00:36:27]:
the future. Michael's not true. Dependabot also recently scans for CVEs.

James Snell [00:36:35]:
Yeah. Okay. Yes. So

Michael Dawson [00:36:36]:
GitHub will if it will push, if it detects that there was a vulnerability, it whenever you push commits to the repo, it will show you that there is there has been, security problems. Okay.

Michael Dawson [00:36:50]:
Good to know. K.

Natalia Venditto [00:36:51]:
Thanks so much.

James Snell [00:36:52]:
Got fantastic. It's a you know?

Michael Dawson [00:36:55]:
I I think The important part is that it just works. Okay? Like, you don't you have to do nothing here. It just detects it automatic. You just need to use GitHub.

James Snell [00:37:04]:
Well, I I think If you

Michael Dawson [00:37:04]:
are a if you are a developer and you're not developing GitHub, well, you know okay.

James Snell [00:37:09]:
I think, though, you have to build a a habit of not ignoring it. I think a lot of folks, you know Yeah. You know, got turned on. They're like, okay. It's there. I'm not you know? And they just don't act on it at all. So I think there, yes, it does require building a

Michael Dawson [00:37:25]:
new habit. Yeah. I guess that comes

Michael Dawson [00:37:27]:
down do that with with a lot of stuff.

Natalia Venditto [00:37:31]:
We know a lot of stuff.

Michael Dawson [00:37:33]:
Sorry.

Natalia Venditto [00:37:34]:
Yeah. Go go ahead, Mike.

Dan Shappir [00:37:38]:
That that's just, like, that comes

Michael Dawson [00:37:39]:
back because the CVEs are not that great. Right? So you can get a lot of noise

James Snell [00:37:44]:
Not that it would come

Michael Dawson [00:37:45]:
really aren't issues, and that that sort of, unfortunately, reduces the benefit of That's

James Snell [00:37:50]:
a little misleading competition. People people ignore medical conditions. Like, what

Dan Shappir [00:37:54]:
do you expect? You know? People like to ignore things.

James Snell [00:37:57]:
Yeah. My my car has been complaining that it needs an oil change for the past month, and I've and I haven't done it yet. So yeah.

Dan Shappir [00:38:06]:
Anything else you want

Natalia Venditto [00:38:07]:
to say about this for Right.

Dan Shappir [00:38:11]:
Look. But to to be fair, people, like, use MP stuff on MPM because they want to reduce their their their workload, and and they don't consider the the load that they're assuming when they do that. And they are sometimes resentful even of it. So it is what it is. But, yeah, definitely, if you're going to be using packages, you need to assume responsibility for the packages that you're using.

James Snell [00:38:41]:
And and I'll just say, you know, it's not just that people get resentful of it. You know? Some people look at what's published on NPM, and they're saying, hey. I you gave me this thing for free. Cool. You're now obligated to support me forever and and answer every question I have to answer. So, no, there is no such thing as entitlement here. If you, if you're using a package, if it doesn't work for you, help maintain it. Don't demand that I do it for you for free.

Dan Shappir [00:39:05]:
I I just want to say that for every anybody who's listening to this podcast and rather than watching it, you're losing half of, Mattel's, input.

Michael Dawson [00:39:18]:
I call them vampires. Okay? I I

James Snell [00:39:21]:
Oh, yeah.

Michael Dawson [00:39:22]:
They they are the vampires of open source. Okay? And, you know, you vampires can be, you know, you need to put out garlic, and you can stab them in the heart with a piece of wood. Right? So that that's what you do with them. Okay? So, basically, there is I have zero tolerance for vampires in any of my reports.

James Snell [00:39:42]:
Okay? Yeah. The problem really is that Dracula was that one vampire in the whole with

Dan Shappir [00:39:47]:
the whole world full of humans. And here in the open source community, it's the reverse.

Charles Max Wood [00:39:52]:
The the the majority.

Michael Dawson [00:39:54]:
Oh, fine. I don't but I'm 0 tolerance. Like, the one that they get really toxic about it. When you tell, nope. It's your bug. It's not my bug. Okay? It's your problem. It's your problem that production your production is broken, not mine.

Natalia Venditto [00:40:10]:
Yeah. But but don't

Charles Max Wood [00:40:11]:
you think

Natalia Venditto [00:40:12]:
it's a cultural pro don't you think it's a cultural problematic system level? Like, we were discussing earlier that developers are not used to sharing and sharing the responsibility. And I totally this is where probably we need to yep. We need to

Dan Shappir [00:40:28]:
educate more on the cultural problem that the majority of humanity are whiners.

Charles Max Wood [00:40:34]:
Alright. I'm gonna I'm gonna derail us back to our node pillars here, and and we're gonna move along to avoid global variables, configs, or singletons.

James Snell [00:40:45]:
Yes. This is a big one. This this catches a lot of people. And it's not just Node. I'm just saying, like, you know, for for for workers, completely different environment.

Dan Shappir [00:40:56]:
It's

James Snell [00:40:56]:
it's programming. Avoiding global is But, like, it was

Charles Max Wood [00:41:00]:
it was it was it was a It's a global problem.

James Snell [00:41:02]:
State. State. State because global you know, individual, like, IO is tied to an individual request. And then if you store global state related to a request, try to exit from another request, ain't gonna work. So, like, here, we made it explicit. Like, don't do this. But, yeah, in node, we run into this all damn time that people just tripping themselves up.

Michael Dawson [00:41:21]:
It's fantastic.

Dan Shappir [00:41:22]:
How how is node different than than general development? Like, I I, like, I I've been writing code for, I don't know, 30 years. I remember when I started building, people were telling me my teachers, my my mentors, whatever, don't use global. Like, what's what's new node that kind of changes the dynamic here?

Michael Dawson [00:41:45]:
A significant portion of the developers that arrive in node. Okay? It comes from a a front end background. Okay? And originally, historically, okay, let's put it in j jquery days, okay, all the state was handled in a global fashion.

James Snell [00:42:07]:
What was the name?

Dan Shappir [00:42:08]:
The DOM.

Michael Dawson [00:42:10]:
And yeah. The DOM. That that comes back to the DOM. Okay? The problem is it's 1 user. Okay? One one browser, 1 user, 1 state. Okay? To some extent, it's super simple. Okay? Makes total sense. Okay? Node.

Michael Dawson [00:42:28]:
Js is not a browser. K? One Node. Js process can handle more than one state. With one exception, if you're deploying on AWS Lambda or so that you or or workers where one request is one state and one user. So you could potentially achieve that, and that's what, you know, those kind of environments gives it to you. Because in fact, JavaScript developer don't seem to be able to understand this principle. But It's it's

Charles Max Wood [00:42:52]:
not a

James Snell [00:42:52]:
little bit of the JavaScript developer. So when we see people in no matter what language they're at I understand. Making basic mistakes.

Michael Dawson [00:42:59]:
Yeah.

James Snell [00:42:59]:
Yep. Yeah. It's and I don't think there's anything unique

Michael Dawson [00:43:03]:
to that. No. No. It's it's probably not. But, anyway, the the a a lot of the a lot of people also saw a part of them. They never know anything different. They come from a diverse background. They didn't study any of this stuff.

Michael Dawson [00:43:20]:
Okay. The other part is a group of people that we used to do all software engineering and do a lot of interface and a lot of things come from a Java dot NET background that when they swap swap to Node, they throw package at all of that and throw it away. And when you show to them how you can, you know, oh, you can actually use this pattern to build a system that is modular and oh, so I can do all the things that I was used to do in in Java or dot net in Node. Yes. You can. And they just, I didn't know.

Charles Max Wood [00:43:56]:
Yeah. So so my question is, like, what exactly is the solution here? Right? Is it is it, like, importing environment variables? Is it

Dan Shappir [00:44:05]:
Learn programming. Right.

Michael Dawson [00:44:08]:
But, I mean, I mean, some things you do have to bring in

Charles Max Wood [00:44:11]:
through configs. Right? I mean, they are essentially gonna be globally available. Yeah. I mean You know, my strike keys or API keys or, you know, you set node and production and right? And that kinda changes the the game. So so stuff like that. Yeah. What what what's the best practice?

James Snell [00:44:27]:
Big one. Defense injection is the big one, for modules. You know, like, a lot some modules and stuff, you know, when you go to require something, you get back some singleton thing. Rather than that, it should return a factory that, you know, that you can use to create your state management. So I think I think there are a number of things. I think some of these are discussed in the, in the blog post, you know, Taylor talking about the talk about them. But dependency and diction is the, actually, is the big one. You want to actually say, you know, for this particular bit of code, this is what I want to make available to that, not just have it generally available for everyone to access.

Dan Shappir [00:45:05]:
Also, you know, if if all your objects are singletons, it's not object oriented programming, and all the data within a global singleton all the fields within a global singleton, certainly, all the public properties within a global singletones are effectively all globals. So in if I'm saying, no. I don't have a

James Snell [00:45:26]:
100 globals. I have just one global, but it has a

Dan Shappir [00:45:29]:
100 public properties, then you've got a 100 globals.

Michael Dawson [00:45:34]:
Yes.

Dan Shappir [00:45:36]:
And in general, we were and in general, we were also mutable state. It's certainly global mutable state.

James Snell [00:45:44]:
Avoid at all costs if you can. And this is the problem with things like, you know, process dot, you know, whatever in node. It's a global it's a it's a global a lot of folks, what we find, are using that for feature detection. Right? They'll say, hey. If process exists, then obviously I'm running a node. Well, no. Because process now exists in d n o and it exists in in bot and it exists in workers. Okay.

James Snell [00:46:07]:
Well, instead of using process, let me look at, you know, process dot whatever property. Well, if the run time start these other run time start also adding that, relying on these globals, just the existence of these globals, just to to depend on where you're at, everything still breaks. You're just shifting the problem. It's gonna break somewhere else. So there's lots of problems with these with these ideas of having these globals. And and it's not just whether you're storing state. It's what decisions are you making based on existence of the global?

Dan Shappir [00:46:35]:
It's user agent strings all over again.

James Snell [00:46:37]:
Yeah. Only maybe even worse because there's so many different ways of doing it. So

Dan Shappir [00:46:46]:
oh, man.

Michael Dawson [00:46:49]:
So we The worst pattern here is those applications that then they are fully configurable using using environment variables. Okay? And the environment variables are spread into a 1,000 different files. So you don't know what are the config and each one has a different default. And you don't know what each of anyone controls. And the only way to know is just grab the full code base. Mhmm. It's a nightmare. Okay? And I don't you know, this is a nightmare.

Michael Dawson [00:47:21]:
So you want to take when your your application starts, you want to take your environment variables or your config. You pass the thing. You'd get the the the values, and then you pass it down to each single application.

Dan Shappir [00:47:34]:
Now you've got a recommendation Especially here. Sorry.

James Snell [00:47:37]:
Go for go on.

Natalia Venditto [00:47:38]:
Especially do do not use KuoBals if you're going to publish like we were suggesting earlier for everyone to consume.

Charles Max Wood [00:47:47]:
Yes.

Natalia Venditto [00:47:47]:
Because I'm being a tragedy.

Dan Shappir [00:47:51]:
Yeah. You're just spreading your your bad habits around and impacting everybody.

James Snell [00:47:56]:
I I would say that modules, you know, any dependencies you're bringing in, do not touch global. I mean, if you're consuming global, like global APIs, like URL, fine. Do not mutate global state from a module, period.

Charles Max Wood [00:48:13]:
So, you you kinda said that there might be configs throughout your app that is the issue that you have your configurations that may be spread across different places where you get them from, or is the issue that you have a lot of places where it changes the way your code works or both?

James Snell [00:48:32]:
I think both.

Dan Shappir [00:48:34]:
So So you manage sorry to interrupt, but I I really am trying to to understand, James, where you get what you're getting at. If I've got, like, what I I like, effectively global configuration. Like, there are certain, configuration flags that impact the behavior of my entire application. Would you rather have 1 module responsible for all con that global configuration and everybody gets injected with it, or would you rather that each model is is just responsible for the configuration that directly pertains to what that module does? Like, what would be your approach here?

James Snell [00:49:14]:
My approach would be that the application should collect whatever configuration is is is available and inject that into the modules. So the module itself should not be looking at process n. It should be relying on what arguments are passed to it from the application.

Michael Dawson [00:49:33]:
100%.

Charles Max Wood [00:49:35]:
So I'm just gonna ask because if there are a lot of places where your configuration can change the way that the code flows through your application, it it almost sounds like feature flags.

Dan Shappir [00:49:47]:
And I

Charles Max Wood [00:49:48]:
know a lot of people use those. So are you arguing against feature flags, or do you see those differently?

James Snell [00:49:53]:
Same different. I I think it comes down to how they're injected into the module.

Charles Max Wood [00:49:57]:
Okay. Yeah.

Dan Shappir [00:50:00]:
The problem is that sometimes it can lead to, having to pass things through, a lot of function calls. Like, you're trying to get a flag way down, and now you've got to pass it through a lot of, you know, a calls b calls c. Now I have to add the parameter to all of these functions, which really don't care about this feature flag just to get it all the way down. So I'm saying, hey. I'm gonna clean the code by just making it global. And now I can access it from from wherever I need to. It's kind of like the problem that React tries to solve with context in a way.

James Snell [00:50:38]:
Yeah. Well, I mean, we have the same like, that's also where async local storage, you know, kinda kinda kinda comes into play, where you can use async local storage to avoid that, you know, having to pass it through each layer. But you still have to make the async local storage variable itself available, you know, to to the various places that it's at. So how do you do that? It it's it's it's it's not a problem free approach. It has its own challenges. Whether you have to pass this thing down or make some, you know, make some things global and other things not, you have to be very intentional and plan it out very carefully. But as a whole, overall, right, relying on dependency injection is gonna be far better a pattern or in a far more maintainable pattern for your application than allowing modules to just arbitrarily access and modify global state.

Dan Shappir [00:51:27]:
Yeah. For sure. Then you need to somebody modified my state, and I have no idea who.

Charles Max Wood [00:51:34]:
Who moved my cheese?

Dan Shappir [00:51:35]:
Yeah. Yeah. I I do want before we move on to the next one, you kind of made an interesting assertion in this, pillar, which is always set NodeenV to production. Can you elaborate why what's you know, why and why is it like

Michael Dawson [00:51:51]:
This is an old battle this is an old battle of mine. Okay? Now there all of this comes from one problem. K? For developers, if I ask 10 developers what the development environment is, they tell my platform. If if you ask 10 ops people, they say, oh, it's some servers running somewhere where the developer test their code. Okay. That's the source of the problem. Right? They we use the same the same term for 2 different things. Okay? Now this means that somebody, somebody bright mind, started put published a module called, config in npm.

Michael Dawson [00:52:47]:
And then that loads you the node_env environment variable for loading up the config file. However, some libraries in, like Express, for example, React and others, changes their behavior based on the node_envenvironment variable being set to production. Now if you are loading the config for your service environment based on that variable, you are essentially your staging environment or anything that is not production, absolutely, you will have massive issues. And that config module is downloaded so many times, okay, which is unbelievable. And, frankly, I it should not be used. Okay? I'm I'm very happy to stand here making this this recommendation. So don't use that module if possible. Okay?

Charles Max Wood [00:53:38]:
So when you say always, you mean when in development as well?

Michael Dawson [00:53:42]:
Yeah. No. I mean, in development is the only moment where you don't set it very often. But whenever you want to do any testing that is relevant to what production looks like, you need to set it to production even if it's a staging environment. So, oh, wait a second. I am using something that controls my environment. Let's call environment. I set it to production even if it's a staging environment.

Michael Dawson [00:54:04]:
Yes. This was such a bad term to begin with. Okay? And such a massive headache pain that, unfortunately,

Charles Max Wood [00:54:14]:
we

Michael Dawson [00:54:14]:
are stuck with. So, and I'm sorry. Like, please don't use again, don't use don't load the configuration based on that variable because it's a bad idea.

Charles Max Wood [00:54:25]:
I've I've had that bite me squarely in the rear end before. So, alright. Just in the interest of time, we're gonna move to the next one. It's handle errors and provide meaningful logs. I'd stand up and scream, yes. Because I had this one hurt me too. But where where are you guys?

James Snell [00:54:50]:
For me, that I mean, just the title of this one is is I think so. It's like that that's that's good enough. They provide meaningful logs. I think I think this is not specific to node. You know, we've we've all had examples of run times where it's just like, hey. Error happened. Cool. Where, how what what what actually is it? Take the time.

James Snell [00:55:14]:
You know, people have to understand that the errors that their their system produces is part of the contract, part of the API. Need to be as intentional about the design of errors as they are about the the the syntax or the or the, the signature of the functions that they're calling, they're exposing. Errors are API. Design them accordingly.

Dan Shappir [00:55:38]:
If your server crashes in the middle of the night and you're told about it in the morning after it's been restarted, will you able you will you be able to do anything about it? If your answer is no, then you've got a problem.

Charles Max Wood [00:55:52]:
Mhmm.

Natalia Venditto [00:55:56]:
Yep. Yep. Yep.

Charles Max Wood [00:55:57]:
Yeah. It's it's it's so rough when you yeah. You have this issue, and then, essentially, you have to go keep going back and modifying what gets logged to try and figure it out because you can't duplicate it in development, and you don't have enough information in your logs to figure out how it happened in production. Yeah. And sometimes there are going to be bugs that way no matter who how good at this you are, but for heaven's sake, you know, if if you if you know that it something unexpected might happen there, you know, you can set yourself up for success by just being aware and then having a good API and a good approach to logging errors.

Dan Shappir [00:56:36]:
Look. You might not have the the proper the sufficient logs the first time around because, you know, obviously, there's a limit on how much you can log and how and you don't want to be, you know, excessively verbose. And there usually also costs associated with with logging. But, you know, at the very least, you want to be able to change log level on some modules so that the next time it crashes, at least then you'll you'll you'll have sufficient context. If you now have to start adding new logs, it's it's going to be a pain. Mhmm.

James Snell [00:57:12]:
Oh, yeah. Definitely. In this in the in the post, there it there's a section provide meaningful logs. Again, it goes back to being intentional, treating this as part of your API and part of your contract. It's possible to go way overboard logging completely useless information that completely drowns out the useful bits of information. So it's like it's as much of a decision of what not to log as it is what to log and where and when. And, you know, there's a whole science to it, but it and it takes time to get right. But you have to put a lot of money to this point, and most people don't.

Dan Shappir [00:57:48]:
And you need to think about what logs at what level, and and can you control levels, like, globally or per module and and stuff like that, or per at least per service and stuff like that?

James Snell [00:58:00]:
And provide details provide enough details that you can filter out the noise that's not relevant to a particular investigation.

Charles Max Wood [00:58:09]:
I was gonna say there are libraries that give you kind of a default format to start from that are typically better than the default logging deal that you get from what you're beginning with. And so, you know, have a look at those Yeah. Figure out what they're doing, and then just just be intentional from there. I may also need to know this.

Natalia Venditto [00:58:30]:
Yeah. If you're a developer tools developer, you also need to to make sure your logs are not too verbose that that go back to the developer with the right feedback and not a lot of noise that is useless to to troubleshoot.

Charles Max Wood [00:58:49]:
Anything else on that one?

James Snell [00:58:51]:
I I will say talk about the cost of logging. It's an it's a fairly old article at this point, but when Matteo and and Dave Mark Clemens and stuff were were were getting started on Pino, They did some research on the cost of logging, the performance cost of logging that, you know, even though the exact numbers and stuff may be different today than what they were back then, it is still an excellent, excellent, read. And, Natalia, if you can provide me with the link to that, I don't have it handy. But

Michael Dawson [00:59:17]:
Of course, I can. It's very old. It's very old. Very old.

James Snell [00:59:21]:
But I I consider it I consider it kind of part of the must read collection of stuff for understanding, a lot of this stuff. It really breaks down why there's a cost to learn, why you have to be intentional about this stuff.

Dan Shappir [00:59:36]:
So, and one more thing I see in the article, Matteo, that you recommend, Pinot as the library to use for logging.

Michael Dawson [00:59:48]:
Yeah. Well, that's what, Dave Dave and myself wrote all those year back, and we saw that logging was the major bottleneck of of most modern applications

James Snell [01:00:00]:
Oh, wow.

Michael Dawson [01:00:01]:
Which is incredible. Like, you know, it's, so the first one was logging. Okay? And the second one was was Express. So I created Pino, and then I created, Fastify.

Charles Max Wood [01:00:15]:
Mhmm. Yeah.

Michael Dawson [01:00:16]:
Okay? So that that was my journey in the, optimizing the ecosystem. So I started creating 1, then I can move I moved from there, moved to the next one. Okay. Done, essentially. And, no, it's it's very problematic. Okay? There is a lot of like, logging is very hard. It's a very hard topic. Okay? Like, either it's a big problem, it's a big pain, or it's absolutely not.

Michael Dawson [01:00:40]:
K? If you are at certain scale, it's a massive

Dan Shappir [01:00:43]:
pain. Oh, yeah. For sure. Like, I I I could 3 the 3 latest companies that I've worked, including the latest one, Sisense, where I currently work. I I you know, you you've got the DevOps person coming up to you and saying, why have we got a 1,000,000,000 logs every day? Do you really need all those logs?

Michael Dawson [01:01:06]:
Yeah. Pretty much. But it also it it's actually, it's actually very hard. It's a very hard problem to fix, okay, and to be able to achieve the right level of granularity and everything. So, with Pino, we have reached a very good, I think, good balance. It works very well out of the box with good defaults. K? But it can also be tuned down for your app to the exact what you need. Okay? And, you know, it has very, very, you know, fine grained configuration that you can put it in.

Michael Dawson [01:01:40]:
And it's very important that you do those things when once you reach a certain level of production.

James Snell [01:01:46]:
For for me though, you know, using the tool is one thing, and and I would recommend Pinot absolutely, you know, hands down. But for me, it mostly comes down to being aware of what you're logging and where what the costs are. If what you're logging are a bunch of large objects are in a JSON serialized, understand that there's a cost to JSON serialization. Right? And if you're sending these massive objects into this thing No.

Michael Dawson [01:02:08]:
It's free, James. Come on. Marshall ing Marshall ing is not free.

James Snell [01:02:15]:
But, you know, it's like, you know, we end up with these with with this code. I'm not I've seen this time and time again where you have these, this this logging logic. Like, hey. We're following the best practice. We're logging on these levels. Well, okay. That level is not activated. Why are you still constructing this massive object, you know, unconditionally passing it off to the you know, when that has its own cost? And, you know, folks need to stop and think about what they're logging and why and how, not just what tool they're using, and understand that this stuff has a definitive cost.

Dan Shappir [01:02:46]:
I'm sometimes so anal on those things, but I guess it's my mentality going back to the good old days of c and c plus plus and stuff like that. It it it really bugs me when I see something being computed for no for absolutely no reason.

Charles Max Wood [01:03:06]:
My my brain seg faulted when you said the good old days with c and c plus plus.

James Snell [01:03:12]:
Yeah. I still have good.

Dan Shappir [01:03:15]:
Guys, I have to I have to drop off because there are sirens here. So,

Charles Max Wood [01:03:21]:
be safe. Stay

James Snell [01:03:23]:
safe. Thank you. Bye.

Natalia Venditto [01:03:24]:
Bye.

Charles Max Wood [01:03:25]:
Alright. Let's let's talk API specifications here real quick. So, yeah, who wants to tackle this one?

Natalia Venditto [01:03:35]:
You know, I'm I'm pretty opinionated on this, and and mostly because of what James just said. A contract is essential. You need to have it. You need to understand how you're going to collaborate with other people. Mostly now that that everyone is on decouple services or a lot of the applications, hopefully, are moving into that kind of architecture. To to make sure that you have the right governance, you need to have API contracts first. So that's 100% a must.

Charles Max Wood [01:04:18]:
Yeah. So you you guys in this one, you recommend either OpenAPI or GraphQL. You said that they it depends on, what you want. Right? They have different strengths. So, yeah, do do you, do you wanna kinda talk a little bit about that? And then, I I'm really curious about generating clients and types because anyway, go ahead and answer that first part, and then and then we can get into the clients and types so I can get some questions there.

Michael Dawson [01:04:46]:
Let me take that very, very briefly, then I'll probably pass the ball to Natalia because she has a different opinion from me. So it's,

Charles Max Wood [01:04:53]:
Oh, nerd fight.

James Snell [01:04:55]:
Yeah.

Michael Dawson [01:04:56]:
So, the open API is great. It provides a map to rest. Okay? So if you know how yours your systems are going to be composed and used, k, This is great. However, they still suffer from, you know, the level of granularity that you're do doing, with REST. K? So it means that in order to achieve a certain, a certain function, a certain central behavior, they will need to, developer using those APIs will need to issue 2, 3, 4, 5 different calls. Okay? Especially from and this adds a lot can add a lot of latency. That's the problem. In, to fetch the data that they need, To get the data that they need.

Michael Dawson [01:05:44]:
With GraphQL, you can actually do that with 1 single pass and have that logic done on the server side. Okay? Which I don't want to go into the intricacy of implementing that correctly, But it it the different use case is if you know if you don't know how your system is going to be read and accessed, GraphQL is a great system, great way to provide discoverability and easy way to consume the data. K? While my under genetic understanding is that using open API can lead to more performant implementations and that are easier to, scale generically. So at the cost of latency. So you see there is there is a trigger. And, Natalia, I know that you you prefer you have a different opinion, so I'll leave

James Snell [01:06:34]:
it to you.

Natalia Venditto [01:06:36]:
No. No. No. I I mostly agree with what you say. Like, I, like with everything else, you need to evaluate your trade offs. What are you what do you want to have? Caching, do you want to have a more granular, or under fetching? Yes. Then go with with a certain pattern or another. I am I am 100% sure that even even if you're doing GraphQL, you need to have a contract no matter what.

Natalia Venditto [01:07:13]:
And

Charles Max Wood [01:07:14]:
That's a good

Natalia Venditto [01:07:15]:
generating your clients is it's right now a possibility. Generating your client on top of the contract is very effective.

Charles Max Wood [01:07:31]:
So that that kind of leads right into this next part, which is generating clients and types. So I have to admit, I've mostly done REST. Where I've done GraphQL, like, I had to build the resolvers and stuff like that. It just felt like a lot of extra work to get that GraphQL to work. I mean, if I was doing front end that consumed GraphQL, a lot of times it was just magic. Right? And so I felt like the the trade off may or may not have been worth it. Am am I looking at this wrong, or is is there something I just haven't seen there?

Michael Dawson [01:08:07]:
GraphQL, okay, removes removes a lot of the like, if you okay. With GraphQL, which is something it's a fantastic system if you have a lot of disjointed teams that do not talk with, anyone to minimize the communication between them. Okay? Essentially, it's a tool that enables, okay. It is your GraphQL endpoint. It's my problem to maintain that the the team that produces it, maintaining and keeping it up and keeping it performant, which it might be very much in trouble in doing so, but it's a business choice. Okay? And then consumers can get that. K? The consumers can just you know? They feel the magic. Okay? Somebody feels the pain.

Michael Dawson [01:08:50]:
Somebody else feel the magic. Okay? With, open with REST and open API, you you probably it's less magical. That's what I'm saying. You can generate

James Snell [01:09:02]:
Hyper. Yeah. Get a little bit of tighter coupling with the

Michael Dawson [01:09:07]:
It leads tighter it genetically leads to tighter coupling.

James Snell [01:09:13]:
Which is which is ironic given REST was originally intended to avoid the tighter coupling, but you still end up with that. Yeah. Well

Dan Shappir [01:09:23]:
So but

James Snell [01:09:24]:
I think I think to Natalia's point, the most important thing is having a contract.

Charles Max Wood [01:09:30]:
Mhmm.

James Snell [01:09:30]:
And, you know, if you can generate code from that contract automatically, cool. All the better. But you have to start with the contract, whatever that is. I mean, you can write the the API contract just in a markdown document and say this is how the damn thing works, but you have to start with the contract

Charles Max Wood [01:09:47]:
first. Yep. Is there anything you wanted to add on those points? Or

James Snell [01:09:57]:
I think Natay and Matteo go read it perfectly. You know, there are trade offs if you can generate. Cool. It's gonna be better for everyone. Whichever one you use depends on what your specific requirements are.

Charles Max Wood [01:10:13]:
Gotcha. And there was a section here about API first versus code first.

Michael Dawson [01:10:21]:
So that is the a different imp pattern. So, there's a lot of debate between all the people that do contract based development that they should start with, this design decide big design session where the contract of the API is defined. K? And then the the people who are writing, consuming it go their merry way, and then the people writing the the API go their merry way. Oh, and that's it? Okay. Bye, Natalia. I don't know. She's gone.

Charles Max Wood [01:10:55]:
Yeah. She said she had a hard stop.

Michael Dawson [01:10:57]:
Yeah. And, basically, one went one way. The other one went the other way. Okay? And then when they try to meet in the end, it never works.

James Snell [01:11:10]:
Mhmm. Yeah. Sometimes it works.

Michael Dawson [01:11:11]:
Yeah. Sometimes it works. I I I don't know. I have I I I'm

James Snell [01:11:16]:
very much a code person, and I'll work back to the API, but then I won't finish the code until the contract is figured out. So, like, it it can work.

Michael Dawson [01:11:24]:
It's yeah. My generic my my experience is the contract is ready when the implementation that implement that contract Yeah. Is ready, is final. Okay? You cannot finalize that. And, therefore, I am more or less saying that, you know, that and then but the key challenge there is you need to keep to uphold the contract. Okay? Once you establish the contract, you need to not break the contract. K? Right. Very important because if you start breaking the this is one of the major causes of downtime.

Michael Dawson [01:11:57]:
Somebody changed an API and said, oh, but these input this thing is now required. It's not. Or these things was optional before, and now, these things was required before is now optional, whatever. Okay? And then the crashes starts happening all over the system, and one little change in a tiny microservice can bring down the full the full fleet.

James Snell [01:12:19]:
Either that or you end up with tons of technical debt and outdated code and obsolete stuff that you have to keep around forever. Yeah.

Charles Max Wood [01:12:27]:
Alright. Well, just to wrap up, is is there kind of an overarching theme or any messages that you wanna kind of add to this, or do we just For

James Snell [01:12:38]:
me for me, the overarching theme is be intentional. Be aware. Like like, pay close attention to thing you're doing, whether it's breaking down the tasks so you don't look in the event loop, to whether it's bringing a new in in a new dependency, to, you know, how you're designing your API. You have to stop and think about what you're doing.

Michael Dawson [01:12:58]:
Yeah. And pretty much all the ones in this list, that's the like, think about what you're doing, and this is almost a nice checklist to go through and say, like, have we been intentional enough? Did we plan what we're doing in each of these places and and go from there?

James Snell [01:13:14]:
Yeah.

Charles Max Wood [01:13:15]:
Alright. Good deal.

James Snell [01:13:17]:
I'm not

Charles Max Wood [01:13:17]:
sure if Mateo is frozen or

Michael Dawson [01:13:19]:
Mateo not

Charles Max Wood [01:13:20]:
he's just is being real.

Michael Dawson [01:13:22]:
God. The family, and I need really need to drop now.

Charles Max Wood [01:13:25]:
Yeah. So I need to say Ciao.

James Snell [01:13:28]:
Great conversation, though. Thanks,

Charles Max Wood [01:13:30]:
man. Yeah. Well, I'm gonna throw in some pics. I don't know if you want to do that too, Michael. But, yeah, let let me jump in here real quick with my pics, and then you can go ahead and throw in yours. Or if James is gonna stick around, he can do that too. But I

James Snell [01:13:48]:
got, like, I got, like, 3 minutes. So

Charles Max Wood [01:13:51]:
Okay. Well, maybe you can go first. I'm guessing you did picks last time.

James Snell [01:13:55]:
Yeah. It did it did them last time. I'm just gonna say something, you know, super simple. Step away from the computer. Go outside. Talk to people. You know? You know, don't get too wrapped up and stuff. Especially folks in the US, you know, things are kinda still, you know, you know, kinda, rather there's quite a bit of turmoil and stuff.

James Snell [01:14:17]:
So just step away. Take a break. That's it. Yep.

Charles Max Wood [01:14:21]:
It's good advice anytime of the year.

James Snell [01:14:24]:
Okay. I'm gonna go ahead and grab one for chatting with you.

Charles Max Wood [01:14:26]:
Okay. Thanks for coming, James.

James Snell [01:14:28]:
Yeah.

Charles Max Wood [01:14:29]:
Alright. I'm gonna throw in my picks here. So my first pick, I always do a board game pick. This last weekend, I was at a board game convention, and I was teaching people the hot games. So my friend picked the games and we taught them at, you know, for free at the tables at the game, or at the game convention. So I'm just gonna pick one of those games. The game that I'm picking and this was a super fun game, it's it was relatively simple to pick up. You know, I can explain it to people in, like, 10 minutes and, you know, it takes about 45 minutes to play.

Charles Max Wood [01:15:11]:
You can play 2 to 2 to 4 players. It's called Gnome Hollow. And, effectively, I'm not gonna give you the 10 minute spiel. I'm gonna give you the 2 minute spiel, and then if you wanna go learn it, you can. BoardGameGeek weights it at 2.17, so it's it's a fairly easy casual gamer game. The way you play it is you are making, like, circles, like mushroom circles. Right? So, you know, there's the kind of mythological, you find a circle of mushrooms and it's, you know, fairy something. So I don't need I don't know.

Charles Max Wood [01:15:48]:
But anyways, you're making mushroom rings and then you harvest the mushrooms from the rings. You take them to the market. You sell them for points. As you create more rings, you also discover different kinds of wildflowers, and so you can collect the wildflowers and those are worth points. And then as you complete rings, you also move markers down onto your board that gives you rewards, and the number of markers you've moved down is also a way of scoring points. Those are the three things that score at the end of the game, the the points you've bought or the points you've sold your mushrooms for, the the amount of wildflowers, different wildflowers you've brought into your board, and then the number of rings you've completed, basically. It it was super fun. Once you play a round or 2, it's like, oh, okay.

Charles Max Wood [01:16:41]:
I totally get how this goes, and so the rest of it is just figuring out which strategies you wanna go for. Right? Am I gonna maximize on flowers, on rings, or on, you know, harvesting and selling mushrooms. And, yeah, it it was really, really fun. Of all the games that we taught, this one was probably my favorite. I did buy one of the other games before the game board game convention because I liked it so much, but I picked it on the show before it's challengers. So, anyway, I'm gonna pick that one, gnome hollow. And like I said, it's 45 minute to an hour game, and, yeah, the the artwork on it is amazing. That always makes it more fun if it's got a good theme and it all kind of is cohesive.

Charles Max Wood [01:17:29]:
A couple of other things I'm gonna pick. I've been watching the show Reacher, and I've been enjoying that. I I just like the way that, Jack Reacher essentially is. I'm gonna do the right thing that I think is the right thing, and you can all just go pounce and and, you know, if you get in my way, I'm gonna make you wish you hadn't. You know? I I just I don't know. I I like to take no prisoners. I'm gonna find the truth approach to life. So, you know, this kind of takes it to an extreme.

Charles Max Wood [01:18:01]:
It's kind of a violent show. So if if that's not your cup of tea, don't watch it. You're right. It it gets a little bit, yeah, just violent. So I'm gonna pick that. And then the last pick along the lines of what James was picking, you know, we just had the elections here in the United States. I know a lot of people have feelings about it. I've talked, you know, I I live in Utah.

Charles Max Wood [01:18:23]:
We're red state. A lot of people are pretty happy that, you know, Trump won and that, you know, the house and the senate. But then I see people kind of taking the task or making fun of people who are sad because, you know, their side didn't win, and I'm not about that. I think some of the ways that people are reacting or overreacting to it is amusing, but I just keep that to myself because at the end of the day, it's not worth it to to demonize or, you know, make somebody feel bad because their side didn't win. So I just encourage everybody to be kind to each other. And then the folks on the other side because I do see the post where it's, like, you know, my my family all voted for Trump, but I'm never gonna talk to him again. It's like, guys, don't do that. Right? Either side, don't do that.

Charles Max Wood [01:19:07]:
You know, everybody has reasons why they voted the way they voted. Some of them are good. Some of them are bad. You know, you you think that they see what you see and then they voted the other way anyway. That's generally not true. I think we all mostly want to be, you know, prosperous and happy and be able to take care of our families and things like that. So, you know, just give everybody the benefit of the doubt, and, you know, if you're not up for having the conversation with people you care about, then don't. But if if you can and you can come to understand a little bit more of, I was really scared that this was gonna happen if Trump or Harris got elected, you know, or I really care about this issue and so I voted, you know, maybe a single issue or mostly a single issue.

Charles Max Wood [01:19:52]:
At least then you can kinda see where people are coming from. And a lot of times you see the humanity in them anyway. So I I'm just gonna encourage that. I'm not really shy about where I come down on this stuff, so you can all probably guess it, but, that's not what this show is about. And I really feel like the best thing we can do at this point is just kind of come together, make sure we understand each other, and then take care of each other. So, anyway, Michael, what are your picks?

Michael Dawson [01:20:17]:
I'm just gonna have one really quick one. Over the years, I've always wished I could, like, print, you know, heads for the little Lego men, you know, to to play around with. And,

Charles Max Wood [01:20:28]:
That sounds awesome.

Michael Dawson [01:20:29]:
Yeah. Makerworld, which is, from Bamboo Labs, they actually have recently they've got, like, I think it's probably AI based or something, but they've got, like, a new a new offering where if you if you log in, you can upload a picture, and it basically will create you a 3 d printable, you know, head of head of that you can then adjust and tinker with just like any other 3 d print. So pretty cool. I wanna do that for all my kids now. There you go. Well, now go to Maker World, and you can they've got they make it easy. So it's pretty cool.

Charles Max Wood [01:21:02]:
Yeah. We're we're we're a Lego family here for sure. So awesome. Well, Michael, I was gonna ask this of everybody else, but they're all gone. If if people wanna connect with you, where do where do they find you?

Michael Dawson [01:21:14]:
I can follow me on Twitter, mhdawsonone. Also on bluesky@mhdawsonwithouttheone, because I managed to get that one first. And, or, you know, in GitHub, very active in the the node project GitHub. So that's the best places.

Charles Max Wood [01:21:28]:
Awesome. I just barely joined Blue Sky. I'm cmaxw just like I am on Twitter. I will say that I am looking to set up, accounts for the shows, so keep an eye out for JavaScript Jabber. It'll probably be JS Jabber unless that's taken. So, anyway, I know people are, you know, again, kind of the political whatever for, you know, I wanna be off Twitter and on Blue Sky. As long as I can reach you and you're happy to get our stuff, you know, I'm happy to stay either place. So, you know, or be of whatever place.

Charles Max Wood [01:22:04]:
Right? So as long as we can connect, I guess, is what I care about. Yeah. Definitely stay in touch there. And until next time, folks. Max out.
Album Art
Structuring Node.js Applications Part 2: Dependency Management, Package Managers, Proper API Usage, etc.- JSJ 661
0:00
01:22:15
Playback Speed: