Don’t pick the best tool for the job when choosing tech stack
Tech stack choices are one of the more significant decisions when creating a new digital product — entire teams can benefit or suffer from these decisions for years to come.
Should we build our app as a Ruby monolith or as NodeJS microservices? Should our data live in a traditional SQL database like Postgres or a NoSQL database like DynamoDB? Should we use a React framework like NextJS, or pass on React and go with Svelte or whatever the cool kids prefer this summer? (I’m too old to know.)
When we compare the pros and cons of different options, we often focus on the technical merits. You may have heard the old adage: “pick the best tool for the job”. It’s great as an expression of technology agnosticism — a fun way of saying “we don’t have an Oracle license to sell you” — but don’t take it too literally. The saying implies that you should rank your options by some metric of technological goodness and pick whatever is “best”. As if second-best just won’t cut it.
Sometimes indeed, second-best won’t cut it. For example, data science projects are commonly built on the Python stack because data science libraries available for Python far exceed what’s available for other languages (with the possible exception of R). It’s perfectly reasonable to choose Python for a data science project on this basis alone. But this is a rare example. A more common scenario is that multiple tools are perfectly suitable for the job, and the decision comes down more or less to personal taste. We’ve all been in discussions where numerous developers advocate why their favorite tech just happens to be a perfect fit for a particular task.
When you find yourself comparing several viable options, take a step back from technical considerations and consider your options from the following 3 viewpoints: competency, continuity, and consistency.
1. Competency
Play to your strengths. When your team is working with familiar techs, they will be able to build a better product and build it faster.
Where is your team’s proficiency? If you have a couple of experienced Java developers who have minimal experience with NodeJS, maybe that new backend service doesn’t have to be implemented with NodeJS (no matter how fashionable it would be). Forgo NodeJS if the team is happy to work with boring old Java.
If the team wants to take the opportunity to learn some new techs, how do people feel about other JVM-based languages like Scala or Kotlin? The jump from Java to Kotlin is much smaller than that from Java to NodeJS, so you can better leverage your team’s competency if you choose Kotlin over NodeJS.
2. Continuity
You won’t be here forever, and your team won’t be here forever. As people move on, there will be a need to find new talent to continue development or, at the least, keep the lights on. This is why it’s not enough to consider your team’s competency: you need to consider market availability for different skills to ensure continuity.
It’s easier to find developers for popular techs and more challenging for esoteric techs. Nowhere is this more apparent than the current frontend landscape. There is a large pool of React developers, and that pool is guaranteed to grow over the next few years (because React is chosen for the majority of new frontend projects, and those projects will need continued development for years).
If you decide to build your new frontend with something esoteric, such as Elm, there is a massive risk that the project will be abandoned or rewritten prematurely. No matter how proficient you are with Elm, no matter how good the front end will be, who will continue development after you’ve moved on? I’ve seen even business-critical software left to rot, keeping the lights on with duct tape — just because the original developers made some esoteric choices. Of course, you could argue that the corporation should simply invest in their developers to ensure continuity of their business-critical software, but that often doesn’t happen in practice. So let’s make it easier for them.
There are differences in degree here. The step from Gatsby to NextJS is small. The jump from React to Angular is significant. The leap from React to Elm is vast. The more esoteric you go, the more you risk continuity.
3. Consistency
Even if we’re building a new digital product from scratch, it’s unlikely to be the first digital product in this company. How were the other codebases built? We should lean towards using the same techs in this new product (to the extent that makes sense). Consistency across codebases is a boon to development and recruitment.
Let’s consider inconsistency in codebases from the perspective of recruitment. Suppose you have a job ad that requires experience in a long list of non-complementary techs. If you need experience with both React and Angular, and also with both AWS and Azure, and also with both Ruby and NodeJS, you’re going to have a bad time. You’re narrowing down the pool of candidates to a small fraction, as very few candidates fulfill your requirements. And if we look at the candidates who pass the bar, the position might not be appealing to them because it’s not very focused on anything.
Let’s consider inconsistency in codebases from the perspective of development. If every codebase is a unique snowflake, learning one will not help you learn the next one. Onboarding times will be long and the velocity of work will be slow even for your seasoned developers if they have to constantly chart unfamiliar territory.
In some ways, the consistency viewpoint is even more critical than the competency and continuity viewpoints. For example, suppose you have a multi-vendor team of 40 devs working on your legacy Ruby codebases. You’re planning to create a new digital product, and the developers who are going to work on it have more experience with JavaScript than they do with Ruby. Should you make the new product with Ruby or with JavaScript? Although the developers have more competency with JavaScript, and although there is a larger pool of candidates available for JavaScript, you’re still going to have those legacy Ruby codebases at the end of the project! You’re going to have trouble recruiting Ruby developers anyway, so don’t make it harder for yourself by requiring those Ruby developers to have JavaScript skills as well.
Recap
When you choose techs for a digital product, consider the following aspects in addition to technical considerations:
1. Competency: techs familiar to your team
2. Continuity: tech skills available in the market
3. Consistency: techs you’re already using in your other codebases