How to choose a tech stack
Introduction
Recenlty at work, we've been preparing for a new and exciting green field project and as with any new endeavour there's been a lot of discussions around what tech we're going to use to build the product. The scope of what we're building is pretty large, creating multiple downstream APIs that all need to be consumed by a single UI. Due to this, we've been exploring using the BFF architecture as we felt this was a good place to start from, particularly where a lot of the views we'll be building will be combining API requests together.
With this in mind, I've been doing some exploration into the different technologies out there to help us achive the desired outcome. I've been focussing on the UI side, with it being my speciality and that will be the focus of this post. I primarily wanted to go through my process for choosing the technology and how to weigh up the pros and cons of each, whilst still taking into account everything we need to consider for the project.
Let's get started.
Choosing which technologies to look at
As part of our investigation, we identified pretty early in the process that we were likely going to use a JS/TS API framework for our BFF. We'd already identified that we wanted to use NodeJS for our API, based around a want to share the data validation between the UI and BFF (using something like Zod) and because by using the same language, we would be reducing the cognitive load of switching between languages when implementing a new feature.
But which JS API framework do you choose? Do you pick something really established like ExpressJS or choose a more modern alternative like Hono. Or pick something a bit more heavy-weight like NestJS?
We settled on some key metrics for identifying which to pick:
- Are they using modern Node & typescript?
- How frequent are updates and releases?
- How big is the community?
These are all important metrics to consider, especially when you're building software in an enterprise setting. We needed to be confident that what we're building is going to be based upon a solid foundation.
As such, we identified a shortlist of frameworks to look into:
Seeing the wood for the trees
Anyone can read documentation all day long and try and make a judgement call for which one of these to pick. But the only way to actually make a firm decision is to actually start working with them.
I created a basic monorepo, within which I added a UI with pages that listed users in a paginated way and had pages for creating and updating users. This would serve as the basis for each framework and gave a short list of features to implement so I wouldn't get carried away. Additionally, I created a set of shared packages within the repo, for things like shared types, utilities and validation schemas that would be used by both the UI and BFF.
That left me with the following endpoints to create:
/users?page;limit;sort;search(GET - Returns a paginated list of users matching the input criteria)/users/:id(GET - Returns the user matching the input ID)/users(POST - Create a user with the input body)/users/:id(PATCH - Update the specified user with the input body)/users/:id(DELETE - Delete the specified user)
Each framework would need to also support validating the input body, query and URL params against a Standard Schema (I chose Zod) and provide intellisense for the output.
As part of this, I was looking at the following:
- What's the developer experience like?
- How easy/difficult was it to achieve?
- How readable is the code?
- How scalable is the implementation?
Each of these questions formed an integral part of the assessment process and were particularly important where not all of our team are confident NodeJS developers. As for the actual work, I built out a proof of concept for each of them; assessing our needs as described above and against the developer experience. You can have a look at these on my github.
Sometimes you have to follow your gut
As with anything, there are always trade-offs with every approach. No solution will fit everyone's needs all the time and so there has to be compromise.
In our case, we've decided to pick Hono. As for how we chose, it's a combination of everything I've already covered, but also going with your gut. I really like working with Hono over the other frameworks, and while there were aspects that I prefer about the others (I particularly liked Nitro) it's about striking a balance between everything and Hono fit the bill.
So what now? Well, we're going to try using Hono and whilst there will always be that nagging question of "should we have picked something else?" I think that part of this process is also trusting that you did your research and staying the course. You can't just switch tech whenever you feel like it; as I said before, there are tradeoffs no matter what you do but by doing your research and actually exploring this technology by building a prototype, you'll be able to figure out what's right for you.
Closing thoughts
Hopefully there's something useful to someone in this post. It's a little rambly but I think the key thing I wanted to communicate was that when it comes to choosing technology for a project, you need to consider how it's going to fit the needs of the project, but also the needs of the developers. There's no point having a framework that's difficult or a pain to maintain and so striking this balance is really key. I think the most valuable thing though, is try stuff out. You really won't know what's better until you try it, and maybe the answer will surprise you.