You're reading "CI/CD and the Snake Oil of Isolation", written on January 30, 2026.

CI/CD and the Snake Oil of Isolation

Since very early on as a developer, I began to wish for my own office. I never did get it, but it was driven by a desire to reduce all possible distractions and interruptions to a minimum. Software is difficult, it takes a lot of focus and everything that isn’t part of the specific problem you’re trying to solve right now becomes an obstacle.

It’s little wonder that developers have such a strong proclivity to seek isolation in all ways - and let’s be clear - most of them are good and necessary. But unfortunately, a lot of the time, the drive to isolate leads to building walls in places that impede rather than protect.

Good examples of this are early and overzealous abstractions, a lot of OOP practices (maybe a future article), and nowadays - microservices.

It’s quite easy to look at the concept and find it immediately attractive. A much smaller piece of code that only has to be correct within itself? It can have its own repo. You don’t have to deal with anybody else’s failing pipelines, weird PR hangups or code style preferences. A kingdom of your own.

Industry hype has given developers carte blanche to go all out on “microservices”, because on paper, it sounds like a great idea. That is, until you actually tally the costs of building those walls.

The Hype

Microservices, repo-per-service, and “team ownership” come with a glossy set of promises:

  • Teams move independently
  • Smaller codebases are easier to understand
  • Changes are safer because blast radius is smaller
  • Services scale independently
  • Clear API contracts mean less coordination
  • CI is faster because each repo is smaller

On paper, it sounds like a tidy little suburb of well-kept houses, each with a picket fence and a responsible homeowner who definitely mows the lawn on time.

No one mentions that all those houses share plumbing, electricity, roads, and a sewer system that nobody actually owns.

Short Term Gains And Long Term Losses

When you split a system, you don’t remove dependencies.
You convert build-time coupling into runtime coupling.

Before:

  • You change a type
  • Tests fail
  • You fix it before lunch

After:

  • You change a JSON field
  • Your service builds fine
  • CI is green
  • Three days later, some async workflow fails in prod because it’s rarely run
  • Slack becomes archaeology

The coupling is still there. It just feels like you don’t have to deal with it in the moment. Breaking it no longer blocks your code moving forward so it feels better, and when the eventual defect comes in, you can treat that as an isolated event.

The Fantasy of Contract Testing

At this point someone says:

“This is why we have contract tests.”

Yes. In theory.

In practice, contract testing often becomes:

  • A few happy-path schema checks
  • Mocked responses that never behave like production
  • Versioning strategies that assume time flows linearly and teams coordinate releases like a ballet

The same teams that wanted isolation for speed now have to:

  • maintain consumer contracts
  • run provider verification
  • coordinate version rollouts
  • simulate failure modes

Does that sound like less work? That’s distributed systems graduate school, except nobody signed up and the tuition is paid in incident retros.

So what actually happens?

We skip the hard parts and rely on:

“It worked in my environment.”

Famous last words of every integration bug ever.

Just Leave It To CI/CD

Every new service and repo adds:

  • Another CI pipeline to maintain
  • Another build image to patch
  • Another place dependencies go stale
  • Another set of secrets
  • Another security policy someone “meant to add later”
  • Another release process with “minor differences”

You don’t get one clean CI system.
You get a pipeline zoo.

There is a funny scene in Hotel Transylvania (the one on the boat) that the werewolf couple goes to the ship’s kids’ care centre and are shocked to learn they will just take their kids and entertain them - intentionally - so the couple is free to enjoy the trip. The scene wraps with a tsunami of beastly little werewolves flooding in and destroying the place.

That is a lot like what happens when a mess of unkempt “microservices” are pushed into test environments to be subjected to CI verification.

Each pipeline is locally “pretty good.”
Globally, it’s a compliance and reliability horror show.

The Feedback Loop Breaks

In a tight system, the loop is:

Build → Test → Ship

In a sprawl-heavy microservice setup, it quietly turns into:

Build → Push image → Deploy somewhere → Wait → Discover integration failure

You are no longer testing your code.
You are testing the current mood of the environment.

And because integration only happens after pushing artifacts and deploying multiple services, failures are:

  • slower
  • harder to reproduce
  • blamed on “the environment”
  • quietly worked around instead of fixed properly

CI stops being a safety net and becomes a polite suggestion.

Cross-Cutting Controls Become Impossible

Want to enforce:

  • SAST?
  • Dependency scanning?
  • SBOM generation?
  • Base image hardening?
  • License compliance?

Cool. Now do it across 47 repos owned by 12 teams, each with:

  • slightly different pipeline YAML
  • different build tools
  • different container bases
  • different definitions of “critical”

At that point “standardization” is out the window and no number of Confluence pages and a quarterly reminders will bring it back.

Meanwhile, Integration Gets Scarier

Here’s the real long-term damage.

When every team picks:

  • their own stack
  • their own repo layout
  • their own pipeline style
  • their own testing depth

This becomes a set of incompatible ecosystems.

Now even when you want to consolidate, simplify, or move faster across the system, it’s expensive and politically painful because teams have already sunk significant cost into these projects.

Technical sprawl becomes an insurmountable obstacle to changes and fixes that might be critical.

Feature Branches in a Trench Coat

Real talk time, dear reader.

Most service splits are not driven by:

  • radically different scaling profiles
  • hard security boundaries
  • fundamentally different reliability needs

They’re driven by:

“I don’t want to wait for other people’s reviews.”
“I don’t want their tests breaking my pipeline.”
“I want to move at my own pace.”

This is the architectural equivalent of everyone at a group project saying,
“Let’s each write our part separately and stitch it together at the end.”

Long-lived feature branches say:

“I want to work safely without breaking main.”

Repo-per-service says:

“I want to work safely without touching your code.”

Both defer integration.
Both feel productive locally.
Both create a nasty surprise later when reality demands everything work together.

You already know how that ends.

You Need A Plan

Engineers are not wrong to want autonomy.
They are wrong to believe isolation gives it for free.

Without a deliberate, top-down strategy for:

  • service boundaries
  • repo sprawl management
  • shared tooling
  • CI/CD standards
  • integration testing layers

the default outcome is integration chaos.

Not because anyone is careless.
Because local optimization is easier than global optimization, and humans are very predictable creatures.

The Boring but Necessary Conclusion

Microservices can be the right choice.
Repo-per-service can be the right choice.

But when they’re adopted primarily as social scaling tools instead of technical scaling tools, the complexity just migrates into:

  • CI/CD
  • release coordination
  • integration testing
  • compliance
  • incident response

And those systems are much harder to refactor than a codebase.

It’s a lot easier to split a repo than to un-split an organization.

So if you don’t draw the boundaries deliberately early,
you won’t end up with autonomy.

You’ll end up with 30 “independent” services
that only work when deployed together
in exactly one environment
on alternate Tuesdays.

✦ ✦ ✦
Share: LinkedIn
Compy says Bye