We Cut Our Release Times by 800%, Mostly by Deleting Our Processes

Dávid
Dávid
Jun 08, 2026
4 min read
We Cut Our Release Times by 800%, Mostly by Deleting Our Processes - by Touch4IT

We had fully automated CI/CD, yet a single release took us 4 hours. Here is how we escaped defensive bureaucracy and got back to shipping.

Over the past few years, we have found ourselves struggling with how much time we spend just trying to release new versions of the software for a client. We wanted to achieve frequent, fast deliveries, but in reality, the opposite was true.

Doing a single release took us easily two hours, just for the backend and frontend. If we had included mobile applications, it would have been a four-hour job.

GitLab CI/CD — builds, deployments

The frustrating part was that we actually had fully automated, functional CI/CD deployments. The code was tested, and the scripts worked, but the deployment itself was buried under a mountain of process. As we grew, we naturally added compliance, traceability, and observability. Every time something went wrong in the past, we added a step to the process “just to be sure” it wouldn’t happen again.

Eventually, all those good intentions piled up into a 15-item release checklist that a real person had to manually fulfill every time we wanted to ship.

Part of some old release checklist

The anatomy of a 4-hour release

When we actually sat down and looked at why things were so slow, there were a few obvious culprits. First, we built more microservices than we needed, which added unnecessary moving parts. But the real issue was the sheer amount of administrative tracking we forced on ourselves.

Just to give you an idea of what a single release required:

  • We had to write release notes in three to five different places, including a Redmine project task, the repository changelog, an internal Mattermost message, and an email to the client.
  • The application version had to be marked in the Redmine project wiki and hardcoded in 5+ locations across the repository.
  • We had to manually link every task contained in the release as a related task in Redmine.
  • Each application release had its own Redmine project version, which meant constantly moving unfinished tasks manually between versions.
  • Developers had to manually create Git tags and merge code into the staging and production branches.
  • To top it off, each platform (frontend, backend, mobile) had to be released by its own platform lead, meaning multiple people had to coordinate their schedules just to push a button.

We were wasting hours checking boxes. We told ourselves this was professional software development, but retrospectively, we were just carrying the heavy baggage of legacy decisions and a fear of making mistakes.

If we wanted to stay competitive, we knew we had to escape this cycle.

Deleting the process

Looking back, we were doing a lot of this stuff purely out of habit, or because we were afraid of making a mistake. It was defensive engineering. But if we wanted to stay competitive and actually ship features to users, we knew we had to escape this setup.

There is an unpopular truth in software engineering that people don’t like to admit: You should not design your daily workflow around a 1% edge case.

So, we deleted a massive chunk of our process.

We removed the redundant tracking, stopped treating versions like sacred artifacts, and automated the few manual steps that actually mattered.

Don’t get me wrong. It’s always important to weigh the risk and the gain. It was all done with such a mindset, and I recommend sticking to it.

Where we are today

Today, our state is completely different. A simple release commit with the version number in the commit message is all it takes. That one commit automatically creates the git tag, builds the images, and deploys everything to the client's staging environment for testing. Task status is automatically updated in Redmine, and deployment info is posted as a comment. Release notes are parsed automatically and included in the email notification. When we are ready to go live, it’s just one more step. A merge to the production branch and the version is out.

Deployment notification in Redmine

Because we removed the friction, we went from struggling to release once every week or two to routinely doing multiple deployments in a single day. This lets us bring tested features to users as soon as they are ready. The time we spend on complex releases is now usually under 30 minutes, and for less complex ones, it’s under 15 minutes. That is an 800% improvement.

Automatically parsed release notes in GitLab release

What about the rare requests from the client or disasters?

Statistically, rare situations for which we had extra steps occur even less than before. We also hardened other parts of our team workflow that led to that. When they do, we handle them. When the client asks exactly when feature X was deployed, we can find it in seconds/minutes at most. When a disaster occurs, we have everything we need to start digging and fixing. There was not a single case in which we told ourselves we were missing information that we would have had if the release process had stayed as it was.

Besides other things, we rely on strong naming conventions, good search engines and logging in internal systems, and long-term partnerships that build deep, shared knowledge across our teams.

Lesson

It is infinitely better not to punish your team with hours of bureaucracy for every single event, just because a few went wrong in the past.