Ferencz Farkas
hi@ferencfarkas.devOradea
Back to work
DevOps & Automation / Case StudyP.02

CI/CD & DevOps

Build, test and deploy pipeline stages on a conveyor, feeding into a cloud target
FIG. 01 — From a TXT file and three manual deployments to an automated delivery platform
Context
3 load-balanced production servers
Before
TXT file, ~50 min manual deploys
After
Automated, ~10 min deploys
Stack
Git, Jenkins, Groovy, Docker, Kubernetes
01 — Context

When I joined the company, deploying software was a surprisingly manual process. The deployment instructions were literally stored in a TXT file.

A developer had to connect to three different production servers, manually update the code, run a sequence of commands, and repeat the process on each server.

The servers were behind a load balancer, but the deployment itself wasn’t coordinated.

It was slow, error-prone and stressful.

A typical deployment took around 50 minutes, and it wasn’t unusual for something to go wrong along the way — sometimes leaving the system partially updated or temporarily unavailable.

We needed to change that.

02 — Get the Code Under Control

The first thing I changed wasn’t Jenkins.

It was Git.

The entire codebase was still in Subversion. Moving to Git gave us much more flexibility around branching and feature development, and it provided the foundation for everything that followed.

We initially adopted a Git Flow-inspired branching model and then adapted it to our own development process as we learned what worked and what didn’t.

This was an important pattern throughout the transformation:

Don’t adopt a process because it’s popular. Adapt it to the way your team actually works.

03 — Automating the Deployment

Once the source code was in Git, the next problem became obvious.

We didn’t want developers manually executing deployment instructions anymore.

I evaluated and experimented with several CI/CD platforms.

They all had strengths and weaknesses. Some had better user experiences, others were easier to get started with, and some offered more built-in functionality.

But I kept running into the same limitation: I wanted the deployment process to be ours.

In the end, I chose Jenkins.

It wasn’t the easiest option.

The UI wasn’t great. Running Jenkins ourselves meant managing controllers and workers, and upgrades could be painful. A managed CI/CD platform would have removed some of that operational overhead.

But Jenkins gave us something I valued more at the time: flexibility.

We could build exactly the deployment workflows we needed and extend them with our own code.

04 — Building Our Own Deployment Platform

The initial setup was relatively simple:

Git → Jenkins → tests → build → deploy

Jenkins handled the orchestration, while shell scripts and Groovy handled the implementation details.

But the system quickly grew beyond a collection of pipelines.

We introduced shared Jenkins libraries and our own Groovy-based DSL so that common deployment logic didn’t have to be duplicated across projects.

Instead of every project implementing its own version of the deployment process, we started building reusable capabilities into the platform itself.

The deployment process became something closer to:

Git push → tests → build → image → deployment

And eventually Docker and Kubernetes became part of the picture.

05 — From CI/CD to an Engineering Platform

As the infrastructure evolved, so did the pipeline. We introduced:

  • Docker-based builds
  • Kubernetes deployments
  • Parallel builds & deployments
  • Shared Jenkins libraries
  • Groovy deployment abstractions
  • Automated testing
  • Multi-stage builds
  • Environment-specific logic
  • Blue-green deployments
  • Canary-style deployments

The important part wasn’t any individual technology.

It was that the deployment process became software itself.

Instead of maintaining a document describing how humans should deploy an application, we built a system that knew how to do it.

06 — Making Deployments Safer

One of the biggest problems with the original process was that deploying the application meant modifying the running production environment directly.

There was very little room for error.

As we moved towards containerized Kubernetes deployments, we could change that.

Blue-green deployments allowed us to prepare a new version separately and switch traffic when it was ready. Later, we also introduced canary-style deployments where appropriate.

This fundamentally changed the risk profile of a deployment. A release was no longer:

Connect to server → update files → hope everything works

It became:

Build → test → deploy → verify → shift traffic

That distinction matters.

07 — The Result

The deployment process went from roughly 50 minutes to around 10 minutes.

But speed wasn’t actually the most important improvement.

The bigger change was repeatability. Developers no longer had to remember a sequence of commands or connect to production servers manually. Deployments became:

  • Automated
  • Repeatable
  • Faster
  • Safer
  • Easier to audit
  • Less dependent on individual knowledge

And because the deployment logic itself was version-controlled, the process could evolve alongside the applications.

By the numbers
50 → ~10 min
Deployment time
Fully automated
Deployment process
Blue-green / Canary
Production deployment
Docker + Kubernetes
Infrastructure
08 — What I Learned

Three lessons stuck with me long after the pipeline was running.

01Automation is not the goalIt's tempting to think that CI/CD means putting a Jenkins pipeline in front of a deployment process. That's not really the point. The real goal is to remove unnecessary human decisions from repetitive, error-prone processes. If the deployment requires someone to remember which commands to run and in which order, the process isn't finished yet.
02Flexibility has a costJenkins' flexibility was a huge advantage for us, but it came with operational costs — controllers, workers, upgrades and maintenance all became our responsibility. There is no universally best CI/CD platform. The right choice depends on what you value: developer experience, flexibility, operational overhead, integrations, cost or control. At that point in our journey, control and flexibility were worth the additional complexity.
03Deployment is architectureOnce CI/CD became deeply integrated with Docker, Kubernetes and our infrastructure, it stopped being just a developer convenience and became part of the platform architecture. That foundation later made our move to the cloud significantly easier. We weren't deliberately building for a future migration — we were solving the problems in front of us. But good engineering decisions tend to compound.
“The best deployment is the one nobody has to think about.”
09 — Looking Back

The most satisfying part of this project wasn’t going from 50 minutes to 10.

It was seeing deployment become boring.

No one needed to SSH into three production servers. No one needed to open a TXT file and follow a list of commands. No one had to wonder whether someone forgot step seven.

The system did the work.

When the deployment process becomes boring, predictable and almost invisible, you’ve probably done something right.

Next project

From Monolith to Microservices

View case study