Join the modern era - deploy every day

Leo Sjöberg • November 2, 2022

When I hear someone say “we don’t release on Fridays so developers don’t have to work late”, I shudder. If you won’t release on a Friday, I’m guessing you’re not releasing one change at a time. If you’re afraid of what a release may bring, you’ve made it too hard to undo. If you won’t release on a Friday, you need to fix your workflow.

Back in 2010, Vincent Driessen of Nvie wrote a hugely influential blog post titled A successful Git branching model. This post took the world by storm, as it introduced the “Gitflow” model. I won’t go into much detail on Gitflow itself – you can read the original post for that. What’s important is that Gitflow gained wide adoption, even in applications that were unintended by the author. For this reason, Vincent now has a “Note of reflection” (from 2020) at the top of his blog post that contains the following segment:

During those 10 years, Git itself has taken the world by a storm, and the most popular type of software that is being developed with Git is shifting more towards web apps — at least in my filter bubble. Web apps are typically continuously delivered, not rolled back, and you don't have to support multiple versions of the software running in the wild.

This is not the class of software that I had in mind when I wrote the blog post 10 years ago. If your team is doing continuous delivery of software, I would suggest to adopt a much simpler workflow (like GitHub flow) instead of trying to shoehorn git-flow into your team.

And if you do a Google search for “gitflow”, one of the first results will be an article as part of the “Atlassian Git Tutorial”, which describes gitflow as "a legacy workflow". It describes it as one which has fallen out of fashion in favour of trunk-based development and continuous delivery.

But what’s wrong about releasing on a schedule? Whether that be weekly, sprint-based, or otherwise?

While releasing once a sprint may seem agile and rapid, it is just another variation of waterfall releases, where you may release once a month, quarter, or year. The longer you wait to release, the more problems you run into. Fundamentally, by planning releases, you’re planning for multiple pieces of work to be released at once. Planning an annual release has more pieces than a quarterly release, which has more pieces than a sprint-based release, but all release multiple pieces at once. This means coordination, conflict, and dependencies. As a result, it’s not uncommon that teams following these release patterns regularly have to take their application offline during a maintenance window to perform a release, or at least do specific planning to avoid downtime.

Maintenance windows encourage unhealthy work-life balance as teams must stay behind outside office hours to perform the release, and makes it difficult to serve customers across the globe. Further, if we want to build a highly available application, maintenance windows are not an option. You cannot combine 99.9% availability with an hour of downtime every couple weeks.

Not to mention that adding more teams exacerbates this problem. More people means more code, which means more coordination and a higher chance of release failure.

To avoid maintenance windows, we must avoid releasing multiple things at once, which means we need to avoid tight coupling between components and applications. This means not making breaking changes, and releasing every change as soon as it’s ready.

By moving towards a trunk-based development workflow, and implementing CI/CD tooling, you can do releases several times a day without worrying about things breaking. You can, and should, release on a Friday, because the risk is minimal, and reverting is as simple as a git revert.

But what about incomplete features? Developers sometimes work on tickets that can't be released on their own, and should be released with other tickets at once. This sounds like you need to coordinate again! Well, yes and no. While you might not be able to release these changes, you can deploy them, because a deploy is not necessarily the same as a release.

This requires some investment in tooling. In order to deploy changes you're not releasing, you'll need some form of feature toggling functionality. If you want a reliable platform, this is something you need to invest in, and to change engineering culture around. Have code be written "flag-first", defaulting to feature flags, so that deploys can be separated from releases. There are plenty of good open-source options, as well as SaaS offerings. The SaaS platform FeatureFlags has an excellent list of open-source tools you can use.

But beyond feature flags, there's really not much more to it, you simply need to write code that doesn't break and separate the concept of release and deploy!

So go ahead, open your pull requests against main, let automated workflows continuously release, and save yourself hours of meetings as you stop planning releases, and start living the unencumbered life of a modern developer.