In the many legacy projects that I’ve been tasked to improve, there are a couple of “necessities” that are non-negotiable when I write-up my improvement plan:

  1. Automated Tests
  2. Automated Deployments
  3. Infrastructure as Code (IaC)

The upsides of these three are a topic of their own, but all of them provide one thing: confidence. Having tests gives my team confidence that their new code won’t break existing features. The ability to auto-deploy upon merging gives confidence that they don’t forget or mistype a command from their deployment runbook. IaC generally means disposable environments: a misbehaving server is no longer a team-wide headache and could be recreated in minutes.

But sometimes, it just doesn’t matter. If winning over a new client hangs in the balance between the hours it take to write a test suite versus deploying untested code, then those tests doesn’t matter. A massive outage happened and your automation fails to spot the problem? Every second counts – comment out that block in your Ansible playbook code, SSH directly on that machine, tinker with files directly. A key part of your infrastructure is giving you headaches, and you only have a day left to finish everything up? Spin it up manually, document your steps, and move on.

We should always strive for perfection, but not everything has to happen perfectly every time. Rules and best practices are there to influence 90% of our decisions. When business dictates otherwise, you do what’s needed. Because in software, like in life, it just doesn’t matter sometimes.