 Hello everyone, thank you for coming to my talk today. My name is Austin Akers. I am a software engineer at Microsoft and today we'll be discussing upgrading to Fastify 3, but more so the lessons learned from doing that. Now, as a brief overview, over the course of this presentation, we'll be going over how we upgraded one of our back-end services, Docs Render, which is a service that improves the rendering and versatility of what we're able to do for the Microsoft documentation from, and as I said, we upgraded it from Fastify version 2 to Fastify version 3. First, we'll give a brief backstory and disclaimer about our code base. Then we'll go over the five lessons and some of these lessons might actually sound more like tips, more so than they are lessons, but nonetheless, five lessons during the process of this Fastify upgrade. And just as a heads up, these five lessons are also the heart of the presentation. And last but not least, we'll then end with the migration summary. Everyone cool with that? Awesome. The backstory. Now, let's start on the backstory and well, for a quick disclaimer for anyone watching this talk, I wanted to talk about our code base before the upgrade. First off, before we upgraded to Fastify 3, our code base was already using TypeScript. Certain topics or points in this talk could prove to be a bit of a different experience for you if you're not using TypeScript. That's primarily because of us taking advantage of the type system provided within TypeScript, right? And Fastify itself along with our code base are both written in TypeScript. Next, our code base really isn't that large. And I say that, you know, relative to an enterprise code base, right? Especially that. Now, I honestly would have to say that our code base would be the equivalent size of maybe View2's code base, maybe Reacts. But I just wanted to highlight that specifically because for individuals who may have a larger code base, the lessons or approaches that I'll be discussing over the course of this presentation may not be applicable to your code base. And last but not least, all of our dependencies were current. While upgrading, we didn't have to worry much about breaking changes in other libraries, which is very nice. So that made the upgrade less complex in comparison to a lot of the upgrades I've done in the past on other projects. Now that we've covered all those three points, let's dive in. Lesson one, understand the breaking changes. Just like with many other libraries and frameworks, major versioning usually comes with, well, breaking changes. An example would be going from View2 to View3. I was gonna say Angular 1 to Angular 2 and so on, right? But if you think of a major versioning upgrade of a library framework is going to break many parts of your application, one thing that you need to do is you need to document the process, right? Document that end-to-end process of how you might want to upgrade and tackle that, right? And within doing so too, assess the possible pain points within your application. For documenting just about anything, I typically use OneNote. I know some people use Notion. I've just simply been using OneNote since college, if probably even high school, right? So I'm just very familiar with that. But utilize that or those applications to map out what parts or files of the code base that might give you trouble over the course of the upgrade. I also, if you don't know already, Fastify has a migration guide. So I recommend if you haven't already, look into that migration guide that is very helpful and there are useful snippets in there that'll show distinct examples from Fastify version two to Fastify version three. And lesson two, fix the foundation and go upwards. Or in other words, establish a stable foundation and build on top of that. When I joined the team and Microsoft, I took the initiative after talking to my boss, setting up my environment and doing what and all the onboarding stuff of saying, hey, you know what? I wanna try tackling this major upgrade. Now, I initially tried the standard approach of version bumping and digging into the large list of errors and attempting to tackle that. Turns out that wasn't the best approach. It was rough. I ended up abandoning and deleting the branch because it was so bad, which brings me to my point, right? This upgrade itself took me several tries. So what I ended up doing was creating a fresh branch and attempted to find a different approach. So what it initially came up with or what we eventually came up with was tackling the upgrade incrementally. So stripping down the app to its basic functionality, fix that foundation and then tackle the upgrade and well, essentially increments, right? So adding on other plugins as well. And the best part about this is that Fastify made that approach easier because of its plugin-centric architecture. Now, as you can see to the right, there are some plugins we've created. And as you can see here, we have render, we have engine, auth, context, content, locale, and error. What I ended up doing was that I narrowed down the functionality to a core plugin within our app and went onward from there. And that core plugin was render, which then, speaking of plugins, brings me to my next point inside of this point, the plugin system. The plugin system changes were probably my favorite. When upgrading the error messages just in general, especially around plugins, were quite helpful. After upgrading our functions, after upgrading our functions became more concise and easier to read. And a great example of that is if you look here to the code snippets from version two to version three. So let's go ahead and take a look at that, right? As you can see here from version two, we're exporting a Fastify plugin. And as you can see here, we have three parameters inside of this. One stating that, oh, this is a Fastify, the instance within this is a Fastify instance. We have plugin options and also next callback. But if we take a look at version three, we're able to consolidate these four lines of code into one line. And that's consolidated into the Fastify plugin callback interface. Now, again, so this right here is a great example of having our function declarations becoming a lot more concise from version two to version three. And on top of this, if you look at it, it's also easier to understand. Now, with all of that being stated, I didn't really just come to this conclusion for the most part from looking at the errors within the error messages in the CLI, right? Although they were very helpful, there was still a level of disconnect on my end on being able to truly understand how certain things work in the upgrade, which brings me to my next lesson, which is also a great point of reference as well. Lesson three, referencing the Fastify test cases. Now, as I stated before, the error messages contained only a certain amount of information. While it was very helpful, I then tried to go out and reference the migration guide. As great as that was as well too, it also still had limited information. And so what I ended up having had to do, what I ended up doing was going inside the Fastify source code and looking at the test cases that implement things that I felt as though I may need or that replaced certain functions or certain interfaces within version two for version three. And a great example of that. Again, if you wanna take a look at this, dive into the Fastify source code inside the test folder, look for plugin.test-d.ts. And what you'll see here is several things we have, as you can see here at the bottom, you'll find a Fastify plugin async test case and you'll also find a Fastify plugin callback test case as well. And these right here, these test cases provided a skeleton for the functions that I, for my functions for version three, for our code base when we are converting it to version three, which is really nice. And to really put that into an example, as you can see here, what we're doing is that we're going to take that test case or like that snippet of code, which is the test plugin async, which is implementing a, as I said, just implementing the Fastify plugin async interface and we're gonna go ahead and try to convert our version two code snippet into our version three. Now, the thought process that I took into converting that version two stuff within our version two code base into version three was specifically wrong plugins was establishing on, oh, is it a plugin, right? Now, as you can see here to the left, we have a site routes, which is a plugin as you'll see, and it's asynchronous, right? And the instance on it is happens to be an instance of Fastify, you know, it parents to Fastify instance, right? So what do we, what can we infer from that? Well, this right here happens to be a Fastify plugin that is asynchronous. And if we look at our version three, let's go ahead and take that information that we learned and implement that, right? So looking at that test case above, as we can see here is that what we've learned is that we now have a Fastify plugin that is asynchronous and for version three, we did exactly that, right? So we now converted that version two code into version three and we can see that we are using Fastify plugin async. So a certain, just a certain thought process that went behind this. And if you really sometimes even just talking out loud and trying to figure out, figuring out a lot of this really comes to help in regards to, you know, in regards to the upgrade as well too. But nonetheless, the test cases proved to be very helpful and that was also a point of reference that I went to a lot over the course of the version two to version three upgrade. Next, lesson four. Now, I always wanna say this, but type script, type script, type script, I cannot tell you enough how having our code base in type script made this upgrade substantially less complex in comparison to what it probably would have been if we were using just vanilla JavaScript and that's primarily because of the type system. Now, just in general, I'm sure you can probably go online and find hundreds of talks about type script and about how amazing it is. But for me specifically, especially when it came to integrating myself inside the code base, but also, you know, just in general, type script is honestly expedited my workflow, right? And over the course of, you know, these, you know, over the course of the upgrade as well, because of type script, I was able to just, I was able to better dissect a lot of the errors that I was getting, right? A lot of these different error messages and being able to dive in, look at a lot of the different interfaces and types and being able to better understand what exactly is going on at the heart of these errors, but also within Fastify as well, considering that they converted their code base into type script. And last but not least, it also lowered the bell curve, right? For me to be able to dive in and to effectively contribute into the code base because I was able to better understand what exactly was going on inside our code base. So as we have here is just a snippet of just a part of the Fastify code base, you know, just for loggers and interface, a logger interface. So now last but not least, we also have lesson five, which I cannot say this more than enough. Having test cases, right? In fact, just having test coverage in general turned out to be exceedingly helpful over the course of the upgrade. Now, again, the test coverage inside our docs render happened to be around 70 to 80%. We had in regards to coverage, right? So we had quite a bit of test cases, right? And just overall, although the test coverage itself wasn't 100%, that's improving, right? Hopefully you hope to get to 100% test coverage inside your app, but 70 to 80% was still very helpful. Now, and just in general, right? Having test cases, and especially during major upgrades like fees with breaking changes, being able to have a point of reference and also being able to check how functionality was before and also after the upgrade, instilled a lot more confidence within the changes that were being made within our application, right? Because the last thing you wanna have are just having some sort of errors that are, there's some silent errors or just errors in general that you just, you know, that will essentially make it just slightly, that'll essentially affect functionality or sort of turn something to be slightly off, right? And last but not least, there was also a level of consistency, right? So again, as I said before, there was that point of reference of functionality being able to know before and after. Hey, this is what our application, you know, how it worked before the upgrade and we're wanting that same end result to happen. So we aren't compromising, you know, compromising our end user experience, but having that level of consistency and being able to check that, you know, before and also after the upgrade proved to be a lot more, just a lot more, just made us feel a lot more confident in regards to, you know, the code base after the upgrade. And if you haven't already, I recommend you play honestly, the best time to get started is now, but if you're looking for a testing library, what we use for docs render is node tap or better yet node test anything protocol is what I'm remembering it as. I'd have to check, take a look, but we're using node tap. So if you aren't familiar with that, search it up, I recommend it, I really, really like it. And what we have here at the very bottom, as I said, insert your code coverage, a test case, a TDD, test-driven development is pretty awesome. So if you aren't doing it, you should definitely do it. Okay. Now, with all those five lessons covered the migration, well, at the end, it was successful, right? But what exactly made that migration or made our migration successful? Well, first off, I mean, we upgraded to Fastify 3, woo, virtual clap. I know, I love the excitement everyone, right? Second, there were no console errors. And that's always a great thing. Third, our code came out to be a lot cleaner and even more concise than what it was in version two of what we're using for Fastify, right? And as we saw earlier in one of the lessons, we saw how we were able to consolidate four lines of code into really one. And I said, as you saw there, it was probably two and that's because of the word wrap, but it was essentially we consolidated four lines of code into one line. And so that conciseness made it, and cleanliness made it much, much easier to read and also reference back to whenever it was necessary when going over the course of the upgrade. And also another thing, many of our test cases didn't break. Now, granted, some of them or quite a few of them needed to just have some minor tweaks and that's because of the upgrade itself, right? When you're mocking certain things, but for the most part, a lot of our test cases didn't break, which is a good thing, which goes to show us that our functionality remained, if not similar, the exact same before, but also after the upgrade with some minor exceptions. And last but not least, what in my opinion is a determining factor, the main determining factor on whether a migration was successful is the deployment. And our deployment was smooth. Now, for recommendations, again, after listening and looking at the migration summary, going over our five lessons, my recommendation for anyone wanting to upgrade from version two to version three, first off, document those changes, right? Document the changes of, and research those changes that might prove to be very intriguing or that might prove to be a pain over the course of that version two to version three to upgrade and also assess your code base, right? Next, work from bottom to top. So establish a firm foundation and build on top of that, right? Now, what we had initially, as you saw, was render was our core plugin. It was the heart of the application. And being able to build up from there made everything much, much easier. And as we started building on top of render, we were able to have even more points of reference, but also having that strong foundation made the upgrade go a lot smoother. And last, and then another thing as well, make sure you reference the Fastify source code and also the test cases. And this goes for almost anyone or anything, anyone who's wanting to find ways or when doing a migration, especially a major migration, wanting to better understand the ins and outs of what exactly is going on and how my code base is affected, but also utilizing that as a point of reference for creating or essentially creating skeletons for a lot of your new functions that you'll be using, right? And another thing that, again, I recommend everyone does is take advantage of TypeScript. If you haven't already, please, please do it. TypeScript is phenomenal. And again, if it wasn't for our code base being in TypeScript, I do wholeheartedly believe that our upgrade would prove to be a bit more difficult than what it already, than what it really was or could have been, right? So, again, TypeScript, TypeScript, and last but not least, having great test coverage in your application. Now, test cases are amazing, but again, we were able to have roughly around 70 to 80% of our app just being covered in tests. So test cases are a great way to make sure that your application has a specific functionality. So before and after the upgrade, having that level of consistency, but also having that source of truth to reference to make sure that nothing breaks silently within your application is fantastic, in my opinion. So if you enjoyed this talk, let's connect. My Twitter is, my Twitter handler is what, TweetMonster999. If you have any questions, again, if you don't wanna connect on Twitter, connect with me on LinkedIn or better yet, if you think I'm pretty cool, which, you know, I think I kinda am, right? Feel free to follow me on GitHub. My GitHub name is BboyAkers. Thank you again for coming to this talk. I hope you enjoyed it. And I hope everyone is enjoying not only just this conference, right? A lot of amazing speakers out here. And I hope that you're able to actually tweet me if you find a really awesome point or something interesting that you found out or something you've learned throughout the course of this conference. So again, thank you. I hope you all have a wonderful morning, afternoon, and evening since we're all around the world. And I hope to see you all again. Thanks.