The team builds logistics software — twelve engineers, one product, and a GitLab instance that five different generations of developers had configured, each leaving their assumptions behind. Their new platform lead arrived in January and kept a diary. What follows is that half-year, compressed: four failures, four fixes, and the quiet month at the end where nothing caught fire. It is the most honest introduction to GitLabOps that a story can carry. The Atlas coins the term for people who run software delivery on GitLab, and the team made every mistake in the recommended order.
January: Counting Before Fixing
The lead’s first act was unheroic: a spreadsheet. Every pipeline, every registered runner, every credential sitting in CI variables, dated. The count embarrassed everyone — pipelines outnumbered repositories, because the same commit triggered two builds each, and nobody had written rules saying when a pipeline should exist at all. The Atlas calls this loop configuration, and its signature failure is exactly that: duplicates and invalid syntax. The fix was a week of writing workflow rules and declaring job dependencies explicitly, so the graph matched intention instead of accumulation.
February: The Queue That Ate a Sprint
With duplicates gone, work piled up somewhere new: jobs parked in pending while developers watched. The scheduling loop had struck its signature blow — jobs asking for tags that no live runner wore. Renaming sprees had left the fleet’s labels aspirational rather than accurate. The team spent three days matching every request to a machine that could honor it, then went further and split the fleet by trust: protected runners for the repositories that could reach production, disposable one-job machines for anything from outside, and a standing ban on shell executors anywhere the public could submit code. The lead’s diary entry ends with a rule the team still repeats: no job waits more than two minutes, at the 95th percentile, before someone hears about it.
March: Naming the GitLabOps Loops
By March the lead had a framework, borrowed from the Atlas, that turned two months of firefighting into a map. The team pinned it to the wall:
- Configuration — files merge into a pipeline graph; fails as duplicates and syntax errors. (January’s wound.)
- Scheduling — tagged runners take matching jobs; fails as pending queues. (February’s.)
- Delivery — releases move through environments; fails as unapproved, unsigned changes.
- Platform — version, capacity, backups; fails as API errors and sluggish repository reads.
The labels mattered less than the habit they enabled: every incident got a loop within minutes, and every loop got an owner within a week. When April’s incident arrived, nobody had to ask which part of the map was burning.
April: The Release That Jumped the Queue
The incident that justified the whole exercise arrived on a quiet Thursday. Production changed without a name attached to the approval, because there was no approval to attach. Two engineers had deployed past each other in the same hour, and the slower pipeline had overwritten the faster one — a delivery-loop failure, textbook. The reconstruction took a weekend; the fix took a day. Environments marked protected, with approvers named in writing. A queue that lines up competing releases instead of letting them interleave. And the guard that retires a superseded deployment before it can overwrite its successor’s work. And a written answer to the question the auditors would eventually ask: who may move production, and how would we know?
May: The Upgrade Debt Comes Due
May exposed the loop nobody owns: the platform itself. The instance trailed four minor versions, background migrations from a rushed patch months earlier had never finished, and repository operations had begun to crawl. The diagnosis was platform-loop in the purest sense, and the lead resisted the heroic big-bang upgrade, doing it the Atlas’s way instead — a modest hop every month or two, pausing at each required stopping point in sequence, confirming every background migration completed before the next hop. Unremarkable, calendar-driven, and by June the crawl was gone.
June: Numbers Instead of Nostalgia
The diary’s last entries are measurements, which is the point the whole story turns on. Merge request feedback at the 95th percentile: eleven minutes, inside the fifteen-minute target. Queue time: under two. Success rate: north of ninety percent. Cost per successful pipeline, newly visible and newly argued over at budget season. The fine print got read too, once someone discovered the platform’s duration figure politely ignores queue time — the very delay February had been about. The team replaced its old arguments — “the pipeline feels slower” — with readings anyone could check, which is the practical difference between a platform that is run and one that is merely tolerated. Arguments did not vanish; they just moved to a room with numbers on the wall.
What This Team Would Tell You About GitLabOps
Asked for takeaways, the lead offers three. First, inventory before improvement; the spreadsheet found problems the complaints never mentioned, including a nightly job nobody could attribute. Second, every loop needs an owner, because unowned loops fail in their signature way, right on schedule. Third, invest at the pace of scale — this discipline earns its cost for a shared, self-managed platform, and would have been ceremony for a lone team on GitLab.com. The full playbooks the team worked from live in the Atlas’s GitLabOps playbooks. Students mapping their own path should read our guide to the knowledge gaps worth filling before interviews, and weigh the credentials question separately in our honest look at what certifications do and do not signal. Stories end; the loops keep turning, and someone has to tend them. That is the whole trade, and it is a good one.
