Paul Mikulskis: Hi there, and welcome to PodRocket. I'm your host, Paul, and today we're joined with Juri Strumpflohner. Juri is the Director of Dev Experience and Director of Engineering over at Nrwl. Welcome to the podcast, Juri. Juri Strumpflohner: Hey, thanks for having me. Hi. Paul Mikulskis: So, Juri was actually on a few episodes ago if you want to check out, we were talking about getting into the beginnings of monorepos and talking about why you would want them, what are they, basics about this, so go check out that episode if you want a general intro. We wanted to have Juri back on because he gave a talk over at VidConf and we're going to get more into the topic of monorepos, minutia about how they're used out in practice and some about what you shared over at VidConf. So, to get right into it, I was asking Juri, what is something that we can immediately hop into that's different from the last episode, because a monorepo's a monorepo, it's not a different thing now than it was in the last podcast we had? So, one of the things you mentioned, Juri, was at VidConf, people seem to know a little less about, or were interested in what is a monorepo? Because it depends on the use case, there's different strengths in the ways that you can set up this developer artifact depending on what your group needs, so maybe we could start and get right into that. Juri Strumpflohner: Exactly. The thing I mentioned before is, basically, monorepos got really, really a lot of traction in probably this year, although they have been around for a super long time. I've been using monorepo without even knowing and just years after, I feel like, "Oh, this was actually monorepo," because I had a couple projects in the same Git repo, but the monorepos can be more, and as you currently mentioned, it depends, often, on the use case. So, if we right now look out in the wild, mostly in a JS ecosystem, that's at least where we currently focus mostly, from an Nx team and from now, we are most situated in that frontend ecosystem. So, if you look at the tooling landscape there and the type of monorepos that we have seen, we try to come up with some sort of classification, because there's a lot of repos out there which are mostly for the targeted, the end goal of publishing something to NPM. For instance, take all the frameworks, like Angular or React, Vite, Vue.js, if you look at their GitHub, it is actually a monorepo. So, they have a couple packages in there, each package has their own packages and their own dependence is declared. They want to still have it in one repo because, obviously, it's beneficial for developing them together, because maybe for Vite, for instance, you have the Vite core package, but then you have, for instance, adapted for React, or they adapted for some sort of other framework. They obviously are kind of related, so you want to have them co-located, basically, if you increment one version, you want to increment other versions, as well, or at least test them in the same PR run or whatever. So, that was one classification and a lot of the monorepos that we see out there follow that type of approach. For instance, you take Lerna, which is the monorepo solution that was there probably the longest in the JS ecosystem. Lerna had the main goal of publishing stuff, so that's also why there's Lerna publish command and Lerna version command, well, because that was the main thing that Lerna was good at. So, we tried to give those types of monorepos a name and we tried to calculate them as a package-based, and so why is that? Well, because you have multiple of those packages that can live independently if you want, so you could really pull them out of the monorepo and push them into another repo and they have all the dependencies with them and they would mostly work. You might have some global tooling and stuff which are repo-wide, but at a high level they would already work on their own, those packages, and so that's why we called them package-based repos. We came up with that name simply because looking from the Nx perspective, where I'm working at, I'm part of core team at Nx, we support all those different styles, but people are kind of confused, because if they look at Nx from their first perspective, they're like, "Oh, well, but isn't Nx about plugins? I heard about plugins there and you need to have single version policy, one version per entire monorepo, so you just have one React version stuff." So, we saw that confusion and we needed an answer to that, to explain to people and say, "Well, sure, so there are different types of those monorepos. There's the package-based, you can just throw Nx on top of it, it would work, it just do the task scheduling. You deal with all the tooling and you don't worry about all the rest. You can set it up basically on your own." And then there's the plugins part, which is another approach to monorepos, which is a more integrated approach, where you say, "I don't know how to best integrate React with Cypress and Storybook and whatnot, so I want guidance." So, that's where those plugins come in with Nx also delivers. We'll help you set that up and manage those tools for you, where you don't necessarily have to deal with the low-level stuff, but at a higher-level, you develop your features in a monorepo, the plugins take care of the building and serving and integrate with different tooling, make sure that integration works, and so that's the second approach to monorepos, which we call that integrated approach. So, you have those two walls, the package-based and the more integrated style of monorepos. Paul Mikulskis: I guess people's minds immediately go to the package-based system, because that's the ethos of Lerna, a little bit, is it's what we're familiar with. So, would you urge people to look at both of those options before starting their project or is there a risk of decision paralysis of... Is this like 99% of use cases are good with the plugin approach, or how do you see that? Juri Strumpflohner: It really depends what your context is about, where you're coming from, basically, and what is your end goal, so I would definitely tell people, "Go check out both of them." We actually did invest quite a lot in the recent months to update our guides on Nx.dev, our docs, where immediately, when you go into the docs, you see both approaches in front there, where you have a small tutorial, which really should take five minutes, covering the package-based monorepo. And then you have a similar tutorial and it does similar steps, it's a package-based, which is more integrated style, so that you can compare them for yourself, where you see, "Oh, well, I did this and this and this in the package-based repo approach, and then let me try this similar tutorial walkthrough with the integrated plugin-based approach. So, what did the plugin do for me? Where can it help?" So, it's really hard to nail those down, especially because we wanted to make it short, so that you don't have to spend an hour or so going through both approaches, but I would totally urge people to look at that and then try to build up your own mind. But to come back to your things, the package-based is probably the first one you would jump at because it looks much simpler, of course, there's no plugins. Well, I work basically however I worked before, it's just that now, I'm in a monorepo. In fact, there, for that type of approach, the main use case we see there is often also an incremental adoption, where you might have already a monorepo, you might have been using something like PNPM or NPM or Yarn Workspaces, which now have some sort of package management stuff in there. So, you might have already used that and you have your monorepo set up, you're a year in or so, and at that point, you're searching for something, that's how many people reach out to us, because it works for them, but it's slow. Exactly. But then it's kind of slow or you want some of more modern features like the caching stuff, so what do you do? So, historically, before they were looking at Nx and they see most of the plugins, and that was kind of our fault, because we mostly talk just about that part, because we see a lot of benefit there- Paul Mikulskis: Because you get excited about what you could do, you're like- Juri Strumpflohner: Yeah, exactly. If you build that stuff, you're like, "Well, you could do this completely automated, you can do automated migrations and stuff," which is otherwise, is not possible. So, we see still a lot of value there, but obviously, being in a position of where folks have already a monorepo, going to that approach would be much harder, because there's much more stuff, the uptake, initially, is much steeper, the curve, where you need to look at the plugins, what it is about, and see how you can migrate. So, that's why we now made those two approaches basically equivalent, where you are much more vocal about if you have a monorepo, well, you can just go and add Nx to it. So, you literally just install the Nx package and then you can already start using it, there's nothing more you need to do. So, it would already give you benefits, in the sense that you can run commands across your monorepo workspace, then you can add caching to it. You already get those benefits which you might want to use in that specific scenario, so you are making, literally, your existing monorepo fast, and that's it. Paul Mikulskis: In the last podcast we have, which again, if anybody wants to learn more about monorepos, we also go into other topics about distributing your app and caching your app, check out our other PodRocket episodes, and specifically the month, Juri, we talked about what happens when you set up Nx? Well, literally, you install it and that's about it, and things start working out of the box, which I think is the big selling point for a lot of people that are trying to get into this. As somebody who's talking to you now that's come from Yarn Workspaces, that was so easy. It felt really cool because Yarn Workspaces, it takes a while, after a bit, once you expand how large your package.json is. Juri Strumpflohner: Exactly. And it should remain that easy. If you're comfortable with that setup, because you have it already working, you know how the package local linking and stuff works by Yarn Workspaces, then if you just have the problem of that speed aspect, it should be easy to add something like Nx, and so we really made it a lot better. For instance, in a last release or the release before, I can't remember out of my mind right now, but what we did is, basically, you can run a command even to do Nx in it in an existing monorepo, and so what that would do is, well, add the Nx package, and then it would look at all your scripts that you have, your NPM scripts and that Yarn Workspace, for instance, I would ask you a couple of questions, in the sense that, "Which scripts do you need to run in a certain order? Because maybe if you build package A should first build all these dependencies and then package A itself," stuff like that. Paul Mikulskis: With some DAG. Juri Strumpflohner: Exactly. But also things like, "Which of those scripts, which are very custom to your own workspace, are cacheable?" Maybe the build link task commands, but then you have maybe some end-to-end, well, that's not cacheable because it reaches out to backend API, so we can't really cache it and stuff, so it asks those questions and then it configures that workspace for you. So, basically, in the end, you end up with that Nx package and then nx.json, which has cacheable operations, [inaudible], and then a list of cacheable operations, and so it's basically that. So, from there on, you can just go ahead, work the same way you did before and enjoy your workspace, with but just faster, because now, you have the caching, you have, potentially, also the remote caching because you can attach it. Basically, it comes with everything that Nx offers, but not the plugins, and so that would be then the second approach that you could then dive in even from there. Paul Mikulskis: Just to be clear for anybody listening, when Juri is talking about this product, it's Nx, as in Nancy Xylophone, the letters. While you were talking, I visited your website, so nx.dev and specifically, if you go to /gettingstarted/intro, that's where you see there's two big boxes that pop up, and you either click on new package-based repo or you can click on new integrator repo, so they're really two top-level, big choose your adventure, so you'll be taken care of if you actually take the time to go read the docs, they're up there. Juri Strumpflohner: It's also interesting. Now that we've made it more vocal, because as I mentioned before, it was kind of our fault, because you could do that already a year ago. To be honest, we improved here and there, some bits, like the Nx [inaudible] command, of course, which didn't exist before, just made it even more easy, but you could always just use the very core part of Nx and just don't use the plugins. But now that we even made that more equivalent, even from entering the docs and everywhere, we also see a transition, where maybe before, we had 80% of integrated workspace and just 20% of the package-based, so now, it seems to even out on both of them and potentially, that might even go be bigger. Especially in the open source JavaScript world, I feel like there's a lot of folks that have already their tooling setup, are kind of comfortable with that, works fine for them, so they would just jump in, and for the new project or whatever, they just spin up a very lightweight setup with Yarn Workspace or something like that. Paul Mikulskis: So, the integrated repo-based approach that allows you to extend your code base through plugins and all these other additional piece of logic you can put in, do you think that is more in line with what Nrwl's end goal for a monorepo system is? The other one is the Step Zero majority use case, where it's like we're putting the bandaid on the wound with this option, but if we were to re-engineer the wheel a little bit and really bring in our magic sauce, that's the direction that your team is... Is that accurate or am I overstepping in that? Juri Strumpflohner: Kind of. I think it really depends on your situation, because what we did, for instance, what we do when we talk to companies and consult for companies, we look at their situation. So, if they have a monorepo already, it's much easier to go into the package-based first and then transition over to plugin-based, if that's what they want, if that's giving more value to them, because you can totally do that. That's also something that we will follow-up in the coming months with strategies of, "Well, I have my package-based, I added Nx, but now I want more automation," and so that's where plugins come in. So, we are trying to currently look at situations where you can mix them, where you just have some part of the monorepo using plugins, but others don't, so basically just where you need them. But the whole integrated approach, really, is something that we see a lot of value in, because we have seen it working at super large companies. The problem is mostly always the timing and the know-how of people working there. Because if you have a large corporation, large teams, 300, 400 developer softwares, and we have seen Nx established in those and we consult for such companies. Then you have a lot of developers, their main focus is just producing features, and so the main issue that you see coming up in the monorepo over time is it becomes really messy, packages cross-importing from each other without any kind of boundaries around. That's not a problem if you are developing your open source project with 10, 20 folks maybe, which are all high experts, most of the time, they really know what they're doing. But in companies, it's more like, "Oh, I need to spin up a library quickly. I need to make sure that that boundary in my monorepo doesn't pull in stuff from that other boundary over there." Basically, you need guardrails in place such that people cannot really go super wrong, so you have some sort of safety net around the various parts in your monorepo. That's where plugins provide, obviously, a whole lot of value, because a plugin, in the end, you can imagine it like a more intelligent wrapper around an NPM script. So, rather than seeing the exact Webpack config or rollout config or whatever, or Vite, or whatever you're using, you see that the plugin on top, which gives you configuration options. So, it's more opinionated, because it limits you in some the choices, because the plugin makes some choice for you already that are probably optimal, especially if you then integrate it with some other part of the monorepo, let's say Cypress or Jest or whatever, or Vitest, so that's what the plugin does. For corporations, this is super valuable, because they can take them, they can even customize them and say, "Well, we create our own plugin, which configures your setup in that certain way, because that's how our coding guidelines tell you you should create that React library." So, what people then do is, well, they just go into monorepo, literally, right click, if they have the plugin installed and the Nx console installed, generate new library, I want to have that React plugin, which respects my corporate guidelines, and then it generates it for you. So, things like that, obviously, provide a whole lot of value, but obviously, you get more tied into a certain type of workflow. So, depending on whether that's something you need to have, yeah, absolutely. Absolutely. That's the whole point even there, to have some sort of opinionated structure. Also, because then, as I anticipated a bit before, features like automated upgrading to the next plugin version, or upgrade from Webpack 4 to Webpack 5, stuff like that, you can only really do it if you have knowledge about that box, which we as plugin authors have. We know, "Well, these are the options you can configure, that's the place where the files live, that's the place where the config lives." So, we can parse it, locate it, and upgrade it automatically for you, which is kind of hard. Upgrading Javas group files is no fun, so you can't really go in there and upgrade automatically, Webpack config, something like that. But large corporations really find it super useful, but coming back, it really also depends on your situation, so I wouldn't push too much into one or the other direction. What I feel is important is that you can choose, you can go either direction and even mix and match, and that's why you're exploring Nx. Paul Mikulskis: Go to the website, look at the docs, because if you guys put effort in the past month, let's have that effort realized and people can- Juri Strumpflohner: Oh, docs are super hard. Docs is like- Paul Mikulskis: I'd love to push people to your docs, because they're really hard and then nobody cares when they're done. Juri Strumpflohner: Yeah, exactly. And then usually, when they're good, you don't hear anything, but if they're bad, people are very vocal about it, which is really good, like they should be. Paul Mikulskis: So, when you were at VidConf, was there something else that people maybe responded to more than you would have thought of when you brought up the topic, or there were more questions about something? Because one of the things that we're talking about now, which is a point of confusion, which was, "What are these two options that you have for the monorepo?" I think another one that you brought up was caching and stuff, and we went into a lot of detail and caching on the last episode and I'm sure we'll get into a little bit more here, but if there's anything else that has come to mind that you're excited to bring to the table or the community at VidConf? Juri Strumpflohner: I think the main point was mostly about how would I integrate my existing stuff, how does that work in a monorepo, which ties very much into overall, how a monorepo works and why you would want to have one. We talked a bit about it in the sense that the colocation part, also things like, as I mentioned before, why does Vite itself develop in the monorepo, all those different packages? They could literally just have different repositories. So, it's an aspect of code colocation, but what I find most important is, usually, being able, in a single PR, to run tests against the various aspects of the entire ecosystem of those packages. Paul Mikulskis: Do you think that this is more apt towards JavaScript projects because of the way that we as developers think? Because when we're in TypeScript/JavaScript land, my brain goes straight modular. I'm like, "What is the smallest atomic piece of every piece of logic I can build?" Whereas if you're building something in Rust, it's a little bit different. So, do you think a monorepo, of course, I've seen in all languages, but do you think it's mostly for this type of development for these developers? Juri Strumpflohner: I think the package-based one might be, because people already immediately, as you say, pushed into that package-oriented thing, which you might even share on NPM, it's small, concise, has one single responsibility, stuff like that. I think that might definitely contribute to the whole part that people are more pulled in towards those smaller pieces. And then monorepo, obviously, is the solution immediately for grouping those together, because if they need to be living together in some sort, then that is an approach that you would go. But I totally agree, also, that you see them across really all sorts of languages. I worked, for instance, years ago in .NET environments and as I have mentioned before, even there, you could have a single web application, [inaudible], NetWeb, API or something, or .NET Core, and you have one project, literally, and that's it, you have folders in there. Or what we had even at that time already did, split them out into separate projects, just link them, which at first, looks like you don't really see the benefit, but literally, that is already a monorepo, where maybe your more feature-oriented business logic pieces, you split them out in different DLLs and you just embed them into the main applications so you can even link them. So, that is also something which I feel is a very much a big driver of why you would want to go into that more modular approach and where the monorepo can help, but they're across every language. We use literally, those monorepo approach, but I didn't know monorepo in the sense of the term monorepo, it just happened that we structured it that way. Paul Mikulskis: Everything gets a term and gets marketable in the developer world, eventually. I was on another episode a week or two ago and we were like, "Why are islands called islands? We were doing this 10 years ago. Oh, wait, marketing, that's why." Do you think that the idea of developing in a linked, we'll call it a linked environment, I don't want to say monorepo, I'll switch between linked and monorepo, just so we're thinking about the higher-level idea here. Is that a beneficial way for us as developers to always move in how we're structuring our projects? Because there's a monorepo solution for everything out there, ultimately, and there are some communities where it's just not practiced as much, so in your opinion, as the monorepo guy, I don't know if you want that title, but you're the monorepo guy, what's your take on other languages and communities using this? Juri Strumpflohner: I think the structuring part is something that people don't immediately see, but it provides, definitely, value, in the sense that, because it's a different... The thing is even if you just go away from the JavaScript world into the Nx example I made before, so why do we pull those out of the folders into different projects? Well, because once you pull it out, you have that technical boundary already around that feature or area, so everything you expose, you need to actively think about it, so you need to think, what are the items that I want to share with outside world? I think that is the key point when you start to modularize your architecture, in the sense of your code base, in terms of organization, because once you pull it out of the modular piece, "Well, this is the API I want to expose," or, "This is not API I want to expose," or, "This is something that needs to be private," and so out of the box, you come up with a cleaner way of sharing things. Well, a folder is always just a folder, regardless of whether it's javascript.NET or some type of code or go or whatever, so you can link into any piece within that folder without having any restrictions in place, so I think that the whole structuring approach is very beneficial. In fact, we have even, a while back, I think I wrote a blog post about how you could use, for instance, Nx, not even talking about monorepos, but just use it as a replacement for Create React App, because what does Create React App do? It creates a new React application, it also abstracts the way the Webpack config underneath, so you don't have to worry about it, but you can just have the features. So, with Nx, you can obviously do the exact same, but you can also start not just having that big application, a single one, but to split it up into those modular pieces, as we just talked about. So, you don't even have to mention monorepo, although it is kind of a monorepo at that point, once you have an app and libraries, but even just from the structural point of view, it helps a lot, because if you have different teams, usually those teams work on different areas and usually those areas are different libraries and stuff, so it's, even from a team allocation point of view, very beneficial, absolutely. I think it depends a lot on how it is being promoted in those different languages, so whether those languages push into those directions or they're more like, "Well, you just developed a small piece inside one project, that's it, and you publish it and you go." Paul Mikulskis: It's definitely going to depend on the phenotype of who actually fills that gap of needing monorepo guardrails around it. I love this conversation, because it's helping me, as somebody who's only used monorepos as a light practitioner, to really wrap my head around this, because a monorepo, when you boil it down, it's the ideas around the underlying actual content. The monorepo is contextual, syntactical, sugar on top that's, as you said, managing what you want to see, what you don't want to see. It's less built-up than maybe we think about it in our head, it's really just organization. Juri Strumpflohner: It can totally just be your single project, you don't even have the intention to put another one. You just started with one project and you split it up into smaller, more fine-grain modular pieces and you just link it into that one single app, that's it, you don't do anything else, but even from that, over time, it just evolves organically. I did that at the company before I actually worked at Nx, we had a similar setup, where we started using Nx, but mostly just for the reason of that splitting up and structuring, because, for me, it made a lot more sense, because you can work on the authentication part, you can work on the more frontend part, even more the sales process part. So, those are all individual aspects of the entire application, but those are separate, you have a single responsibility and stuff, so that splitting up helped a lot, have those cleaner separations. It just happened that at some point, it's like, "Well, we need also mobile app." We have to use Ionic and immediately, we could reuse some of the pieces. Why? Because they were like libraries, they weren't meant to be reusable out of the box, so you have to just or maybe even refactor out, split one library into two or stuff like that, but it is already there. So, even by looking at the structure, you can already see, "Well, this could be something reusable and this and that," while if you just have that big monolithic application structure, it's much harder to impose such a structure. I totally find that fascinating, that approach of structuring code. Paul Mikulskis: The last big benefit, I guess, that comes to my mind immediately, that you get to modularize everything, is now you can index and cache it at different levels. So, if you want to hear more about the tech caching, I'm like a broken record here, but for the third time, go check out our other episode. But Juri, just really quickly go over this, you want to talk about how incredible Nx's caching is? You're going to see build-time improvements, you're going to see, honestly, more just secure distribution, distributed build process for your application, that's just the tip of the iceberg, but what do you think is the big selling point for most people when you talk about caching? Juri Strumpflohner: The thing is, once you enter a monorepo space, regardless whether you have multiple apps in there or just a single app split up into smaller libraries and pieces, now that you have those individual pieces, you can run them individual, so testing or the building of. Let's say you have just that out sales and, I don't know, design system library in your application. Now that you have the design system part split out into seeing the library, well, you can just run tests against that single one, rather than the entire application, and then just focus on that and, obviously, speed up things. Because the thing is, in the monorepo space, once you start in that part, you see the benefit of the code sharing and all those things that we touched on, obviously, as you add applications, your build times will go up, naturally, of course, because you now, you have just one app and tomorrow, you have two, three, four, and so it increases, even if the single builds are fast, if you have to run always all the builds, it will slow down. So, again, that's why you need some sort of solution that can do those more intelligent things running just whatever got factored in a single PR or things like caching. Paul Mikulskis: I was just going to say if think about if you were a developer and Docker caching didn't exist? You would be living a sad- Juri Strumpflohner: Exactly. Paul Mikulskis: ... slow life. Juri Strumpflohner: Absolutely. That's a good analogy, because it's the same thing, you want to have those multistage setups where you don't have to build everything from the ground up every time, and so it's a very good analogy to the monorepo part. Well, once you have a larger monorepo, you just want to really touch and run whatever you changed and run modified in that specific PR. The caching is something that adds on top of it, because especially, if you have your CI system and you distribute your cache, where you can benefit from a central, you could think about a center storage where all those caches live, if you can pull from those caches, well, then it gets even faster on your machine, as well, and not just on CI, because you don't even have to run certain commands anymore, because maybe you pushed up just that change before your PR ran through the test run-off the design system. Well, I didn't touch the design system, but it gets affected as part of some other change on my side, but it wouldn't run, because you already did that, you already built it, you already ran the test for it, and so that's where the caching comes in. Paul Mikulskis: Does the more complicated integrated repo approach take advantage of caching in ways that are unique to that more setup than the package-based? Juri Strumpflohner: No, not necessarily, because the caching lives really at the core part of Nx, so the plugins are really something on top of it. Plugins usually help with code generation, automate migrations, that type of thing, but the caching is at the core. So, basically, you can see it at the process level, because if you add Nx without the plugins, it's really just like a fast task scheduler. With that, Nx has the knowledge where when it runs a task, you can tell Nx, "Look, those are the input files, those are output files, or folders or whatever," and so Nx really just caches that as a black box. So, it runs the task in an efficient way, it gets the results, it stores them in a cache with a hash code, and then next time you run it, it just compares, "Did I see that hash already? Yeah, it just let me restore everything." We actually go really deep on that side, we even go so far that we don't even rewrite again the file system if the files already there just to speed up things, because obviously, file system writing is costly. So, let's say, you build your package and that produces, obviously, something in this folder, like JavaScript and CSS files and stuff, we don't rewrite that if that's a CSS file, it's already there, and it's the same as in a cache. So, we really optimize down to the lowest level, but that's actually what the caching does for you. That is already in the core of Nx, so regardless where you go, more the package-based approach or the more integrated approach, you would benefit the same way. Paul Mikulskis: You'd get both of them. Juri Strumpflohner: Exactly. The stats there are really crazy, especially if you distribute them, that's the key goal, in the end, locally on your machine, it always caches, so you would get fast runs, but obviously, it makes much more sense if you're integrated with your CI system and even shared across coworkers, so your own builds get faster even by using caches from our machines. But now that we have those cache results aggregated, we also looked at a couple of stats and those are crazy. We pulled them out, I think they're from, let me actually look at them, I think they are from three weeks ago or something. But basically, on the public cloud, because we have public cloud version where you can connect to, but we also have on-prem solutions, for which we don't have stats, because they live in the companies' own networks and Kubernetes clusters or whatever they have set up there. But just from the public cloud version, in a week, we save around seven years of caching, so there's seven years of computation time saved per week, which is kind of crazy if you think about it, because those are products that never ran, on a CI system, they would have never executed, but you just got the result back and that's it, that's literally computation time saved, basically. Which was also the reason why, at VidConf, my talk or something, speed up your CI with caching to save the environment. Paul Mikulskis: That's what I was going to say. You're saving so much CO2, that's an immense amount, immense. Juri Strumpflohner: Absolutely. Because that's not a machine that gets spin up, there's no energy consumed. That's a process that didn't run, although it would have run otherwise, so it's kind of fun. This is just from the public cloud, because we have savings from customers on-prem, which one of the biggest, they save, I think 14,000 hours a week, it's crazy, that's a week, that's just from a single one. So, it's impressive how much time went into that and how much time gets saved from just really caching stuff. Paul Mikulskis: It boggles my mind, just in general, to wrap your head around what isn't cached and what could be cached, because we're at a point of tech now where it's easy to just be wasteful, it doesn't cost us extra. So, when you step back for a second and you're like, "Wait a minute, I already did that," it happens a lot, way more often than we think, and I think these stats you're pulling out really exemplify that. Seven years, listeners, seven years, that's pretty crazy. Juri Strumpflohner: Just in a week, that's just in a week. It's crazy. Paul Mikulskis: I wish I was better at English, that's a ludicrous speed. Well, Juri, thank you for your time. We could keep going on about this, but we're almost at 40 minutes, again, look at us. So, I'm going to throw one link out here for the listeners, which is the Nx.dev/getting-started, getting-started, there's a dash between it, /intro. Nx.dev/getting-started/intro. So, you can find the guide about the package-based repo or the integrated repo, what we spent a lot of the time talking on the podcasts today. If you want to learn more about the caching, we have that other episode. Juri, if people want to find you on Twitter or the blog that you mentioned, where's your blog located? Juri Strumpflohner: We mostly tweet and blog on NxDevTools, so if you go at @NxDevTools, that will be the Twitter handle for Nx itself, it's the same handle we also use on YouTube. The blogs, we crosspost them usually to dev.to, which is the easiest, so dev.to/nx, you would find all the blogs there. There's also the blog post about the cache savings and helping environment stuff. Because there's a fun website where you can actually give it the cache results, the time saved, it would translate them to CO2 emissions, which is pretty interesting, because then you can compare, "Oh, that was actually be a flight back and forth to New York," or something like that, which is like, "Oh wow, that's great," so it's fun. Paul Mikulskis: So, really, you could compare with the hash of the cache and it would give you how much was this saved? Juri Strumpflohner: No. Basically, you can go to the website, there's a website out there, I don't call recall it out of my box, but it's linked in the blog post, where you can give it what is 20 hours of computation on a media machine, on AWS, or something, where you would run your builds, basically, and it would then tell you, "Well, that would be like a flight from New York to San Francisco or like driving a car for a year," or something like that. But it gives you more feeling of the CO2 emissions which go into that computation. Paul Mikulskis: Well, thanks again for your time, Juri, and hopefully, we can turn some more people onto Nx after this, as is always the case, with these episodes and save some more trees, and their time. Juri Strumpflohner: Thanks for having me.