Skip to content
Kien

What owning a release train actually means

· 4 min read

Eight gateway services, one shared integration branch, and a promotion to production that is a deliberate, batched act with a human at the button. What "the unit of release is the set, not the repo" looks like when it has to run every week instead of sitting in a principles list.

  • release engineering
  • multi-repo
  • process
  • CI/CD
On this page
  1. The train is a branch
  2. The unit of release is the set, not the repo
  3. A human presses production
  4. "Go-live" became a verified claim
  5. The number I do not have

"Release train" is usually decoration — a phrase that makes a deploy schedule sound like infrastructure. I want to write down what it means when it is literal, because I own one, across eight gateway services, and most of what makes it work is invisible from the outside.

The train is a branch

Work merges into one shared integration branch. That branch collects: a fix here, a supplier integration there, a mapping change, a refactor. Merging into it releases nothing — it is the platform where the carriages accumulate.

Promotion of that branch to production is a separate act, and it is deliberately batched. What goes out is not "whatever happened to merge today"; it is a set someone looked at, as a set, and decided to send. The question at promotion time is not "is this commit good?" — that was answered at merge time. It is "is this combination good, across all eight services, in this order?"

Every push bumps a version. That sounds like bureaucracy until the day you need it: "what is running in production" is always answerable with an exact number per service, and "did the fix actually go out" stops being a matter of opinion.

The unit of release is the set, not the repo

That sentence sits in the How I work list on this site, and it is the whole design in one line. A go-live can span eleven repositories. When it does, the merge order is part of the design, not an afterthought: backend contracts land before the consumers that read them. Run it the other way and there is a window where a consumer asks for a contract that is not there yet — and in this domain that failure is rarely a crash. It is a wrong number, computed confidently.

So the order is written down with the feature, the way a schema migration is written down with the code that needs it. Deciding it on go-live day, from memory, is how the window gets opened.

A human presses production

Deploys go through manual CI pipelines. A person presses the button, and the production stage asks for explicit confirmation before it runs.

I know where the industry's centre of gravity is, and this is not it. Continuous deployment is the right answer for a lot of systems. This one sits between partners and suppliers, and its characteristic failure — documented elsewhere on this site — is not an exception in a dashboard. It is money counted wrong with no error anywhere. For that failure shape, I want the moment of irreversibility to have a person in it, and I want the batch to be something that person can hold in their head. The cost is latency and a human in the loop on a Friday evening. I pay it on purpose.

"Go-live" became a verified claim

The reason I trust none of this to discipline alone is written up in the cross-repo go-live case study: a feature that spanned eleven repositories shipped with one repo never on the list, and production spent four days charging less than the UI showed — with no exception thrown anywhere.

After that, the check became a tool: a reusable multi-repo checker that verifies a feature actually reached master in every repository it touches, before anyone declares go-live. The word "go-live" changed grammatical category — from an announcement someone makes to an assertion a tool has checked. A human still says it; the human just is not the evidence anymore.

The number I do not have

The honest ending is that I cannot show you a before/after incident count. The case study documents two incidents from one go-live run the old way; nobody was counting incidents-per-release before that, and there is no counter of the incidents that did not happen since. Publishing "incidents down N%" here would be exactly the kind of unmeasured, flattering number this site exists to refuse.

What I can count: eight services on the train, one integration branch, eleven repositories at the widest, one checker, one confirmation prompt in front of production. And one category change I can point at: "did everything land?" used to be answered from memory, and is now answered by a tool that does not get bored on the eleventh repo.

That is what owning a release train means. Not the schedule — the batch, the order, the button, and the proof.

Related posts

· 5 min read

A list of things that are contracts without looking like one — an identifier a client holds between two calls, a documented error code, the difference between a field being absent, empty and null. Why adding is nearly free and removing is a coordinated release across repositories I do not deploy, and what it honestly costs to keep everything working.

  • API design
  • backward compatibility
  • multi-repo
  • release engineering

· 6 min read

Review technique after a year of reviewing for six engineers: the three things a review is actually checking, the one thing it is not for, why every comment now says in its own text whether it blocks, and the four questions I ask of any change that touches money or state. No review-time or defect-rate figure was ever measured — what is countable is what the reviews left behind.

  • code review
  • craft
  • process
  • team