How to Choose a Web Tech Stack

Anyone new to web development can be overwhelmed by the unending supply of choices for tech stacks. Teams just getting started in the industry lean toward something easier to pick up and learn. Teams coming from other platforms such as embedded or desktop dev tend to stick with tools and languages they’ve always used.

Both of these approaches are rational, since they each prioritize getting up to speed quickly–in other words, learnability.

I’d argue, however, that learnability shouldn’t be the primary consideration when choosing a tech stack for web development. Instead, automatability should come first, followed by applicability, and finally learnability.

Once Upon a Time, Everyone is a N00b

As someone who came into web development from desktop and command-line tool development, I, too, prioritized learnability when choosing my first web tech stacks. Looking back, I realize that my choice was heavily influenced by the cognitive bias known as the availability heuristic.

I focused on the problem immediately in front of me, and optimized to reduce the amount of time I’d have to uncomfortably fumble around with my dev tools. Fortunately, learning web development principles was the goal of my first few projects.

What I didn’t know back then is that, over the course of a long-lived product development project, the cost of learning is easily dwarfed by:

  1. The cost of a broken deployment process—a stack’s lack of automatability
  2. The cost of bending a framework to do something for which it wasn’t designed—a stack’s lack of applicability

Why is this true? Relative to the the duration of a project, the learnability cost of ramping into a tech stack is constant, whereas the cost of lack of automation and applicability is proportional to the duration. Let’s dig into the cost of each consideration a bit more.

1 – Automatability

I like to split software project automation into three categories: environment, testing, and developer tasks.

Environment

Environment automation means going from nothing to a running, independent application environment with the push of a button. This is valuable for two reasons. First, it enables brand new team members to get up and running right away. Second, it paves the way for on-demand deploy environments, which are key to unlocking an efficient and scalable deployment pipeline. A tech stack requiring a novel or difficult-to-replicate environment will make achieving this goal more challenging.

Testing

Testing automation requires two things. First, we need to easily get results from your test suite via some non-GUI interface (e.g. command line output, JUnit-compatible output files.) Second, we need to easily launch, instrument, and deploy the full application to build a reliable end-to-end or integration test suite. Tech stacks requiring a GUI or visible IDE to execute tests and launch an application in dev mode create a huge barrier to entry for reliable test suites in continuous integration.

Developer tasks

Developer task automation is about translating manual processes into code. For example, source code files for a new module and corresponding unit tests can be generated by a script. Requests from stakeholders that require running common queries in the production database can be wrapped in command line tools. A deployable build artifact can be created and deployed on each CI build.

The easier a tech stack makes it to create a new, one-off tool, the more manual tasks your team will automate. Rails, for example, makes it simple to add custom Rake tasks that are executable via the command line and can be implemented independently of its application framework patterns.

Tech stacks that are able to be deployed within Linux or containerized environments tend to provide easier options for automation. The CircleCI and Heroku services take advantage of this fact. They’re both able to assemble a Linux-based execution environment tailored to your project with little need for configuration beyond what they infer by inspecting your codebase.

Cost

The cost of poor automation is incurred every week. Tricky manual production deployments, non-identical handmade dev environments, shared deploy environments for feature review, unreliable end-to-end test suites–they all add up to a significant amount of drag on a team. Poor automation can also kill a team’s sense of confidence in making changes to the codebase, let alone deploying any of them successfully to production.

2 – Applicability

Almost anything sufficiently heavy can serve as a hammer if you swing it hard enough. Likewise, almost every web tech stack could implement any conceivable web app. Choosing one that fits your problem will reduce the effort and cost required to accomplish your project’s goals.

Ruby on Rails is a good fit for a back-office administrative CRUD interface. Node.js is a better fit for a backend API handling a large number of long-running IO-bound requests. Ember.js and React.js + Redux are great choices for an SPA managing complicated client-side state.

The cost of a tech stack with poor applicability is also incurred each week. This usually comes in the form of writing custom code to accomplish a task for which another tech stack could provide an out-of-box abstraction.

A more obvious form is when you feel like you’re actively fighting an application framework. For example, Rails doesn’t make it easy to build an application without a foundation of restful resources. Nor does it like having validation logic defined outside of an active record model.

3 – Learnability

Ramping into a new tech stack is never free. However, presuming you make progress on the journey from n00b to expert, you can consider the cost to be front-loaded and out of proportion to the size of the project. The longer a project lasts, the more the you can amortize the cost of ramping into a tech stack. Contrast this with the costs of lacking automation and applicability. Unlike learnability, their effect is multiplied by the number of weeks spent on the project.

Full-stack web development covers many bodies of knowledge: HTML, CSS, HTTP, relational databases, asynchronous processing, and JavaScript, just to name a few. Developing an application subordinated to HTTP’s request/response paradigm, with a time limit to process each request, which needs to be scaled arbitrarily and upgraded without downtime, is very different than desktop, command-line tool, or embedded development.

Most web tech stacks build on these constraints and presume a basic knowledge. Once a skilled software engineer learns the first web tech stack, ramping into the second will likely require much less time. There’s just way more stuff to learn about general web development than there is in Rails or Node.js.

Closing

I have the luxury of working with a group of talented folks at Atomic Object who by necessity learn and use many different tech stacks as part of their full-time jobs. Because of this, we’re all experienced with learning new tech stacks quickly. We’re not, say, just a “Java shop.”

Now, say you are in a Java shop or a .NET shop. If you’ve read this far, you may be asking yourself, “Nice story but yeah… we’re gonna use (Java|C#). so what the hell good is this to me?”

I encourage you to look at these three services: GitHub, Heroku, and CircleCI. Choose a tech stack supported by Heroku and make a basic hello world app. Explore Heroku’s Pipelines and Review Apps features. Connect your app to CircleCI and look into their deployment automation and test parallelization features. Work your way backward from there to understand your project or team’s true constraints that would leave you in a deployment environment without on-demand deploy environments, or with a build server you have to manually maintain.

Even if you determine you can’t deploy to a containerized environment like Heroku or use the best CI as a service platform, CircleCI, you should at least move forward knowing what you’ll be missing compared to what’s possible and widely enjoyed by many seasoned web developers.