Independent CI/CD pipelines: where a shared build breaks
While there are five services, a shared build looks convenient: one configuration file, one set of checks, one artifact at the output.
With thirty services, the same scheme becomes a pipeline bottleneck — a change in one module triggers a full rebuild and queues releases of teams that changed nothing.
The cause is usually the absence of a dependency graph. The trigger fires on any commit, the dependency cache is shared and invalidated entirely, and blocking checks — linters, tests, vulnerability scanning — run across the whole repository, although only one service changed.
A shared image tag makes the picture worse: neighbors that do not depend on the change also have to be rebuilt.
Then the queue effect kicks in. Build time grows linearly with the number of services, not with the size of the change, so waiting for available runners becomes the main source of downtime.
Teams start accumulating changes into one large release, rollback affects several services at once, and quality feedback arrives in hours instead of minutes.
We explain how this is solved with independent CI/CD pipelines: each service has its own set of triggers, isolated cache, its own artifact, and a clear area of responsibility for the result.
What build separation gives: speed, isolation, predictability
When there is one build for all services, any change in a shared library pulls a rebuild of the entire tree. Time grows linearly with the number of services, and the queue on shared build agents becomes a bottleneck: a developer waits for the result longer than they write code.
Independent pipelines break this link — a service is built and checked only when its code or its dependencies changed.
Failure isolation is the effect noticed first. An error in one service's tests no longer blocks the release of the others: the build fails in its own branch, while the rest continue.
The class of incidents "one falls — all stop" goes away, and failure boundaries are visible per service instead of drowning in a shared log.
Reuse of dependencies gives acceleration without loss of rigor.
The cache of layers and artifacts is tied to the manifest hash: if the dependency set has not changed, the installation step is skipped and the ready result is taken — build time is reduced from tens of minutes to single-digit minutes, and the more services use a shared set of libraries, the stronger the effect.
Fast release rollback is a consequence of the same separation. Each service is released and rolled back with its own artifact version: returning to the previous image does not require rebuilding neighbors and does not pull in others' changes.
In GitLab CI this is expressed in path-based trigger rules and separate environments per service; the same model is reproducible on any mature build tool.
Overall, release frequency grows: a release stops being an event for the whole team and becomes a routine operation of an individual service.
Ways to organize pipelines: comparison of options
The model for organizing CI/CD pipelines is chosen not by team size, but by how much services diverge in build stack, release frequency, and isolation requirements.
Pipeline boundaries coincide with responsibility boundaries: the more autonomous the team, the more expensive a shared pipeline is to maintain.
In a monorepo, the same models offer different trade-offs.
A shared pipeline builds everything on every commit, a template pipeline keeps a unified standard of stages while each service has its own triggers, and separate pipelines provide independent release but require discipline when editing shared libraries.
| Option | When it fits | Limitations of the approach |
|---|---|---|
| Shared pipeline | 3-5 services with a similar stack and a common release cadence | A change to one stage affects all services; a build failure blocks the rest |
| Template pipeline with inheritance | Dozens of services, a unified check standard, and different triggers | Template backward compatibility: a breaking change to a stage requires migrating all inheritors |
| Separate pipeline per service | Autonomous teams, different stacks, independent release | Duplication of stage descriptions; divergence of check versions between services |
| Monorepo with affected service selection | Many services in one repository, frequent shared changes | Requires accurate dependency graph analysis: an error leads to a missed release or extra builds |
What to check before choosing
A practical criterion is the cost of change: how many services will be affected by editing one stage. If the answer is "all," it is time to move from a shared pipeline to a template or separate pipelines.
Work sequence: from pipeline audit to handover to the team
Splitting a shared pipeline into independent pipelines begins not with editing configuration, but with inventory: until it is clear what exactly runs on every commit and what of that actually depends on the changed code, any changes produce random results.
Below is a sequence in which risks are removed one by one, and the team receives a working scheme rather than a set of files.
- Pipeline audit. We compile a list of builds, triggers, and stages, measure the time of each, and find blocks that are duplicated across all services. The output is a picture of where the build sits idle waiting for someone else's result.
- Dependency scheme. We record which services are linked by shared libraries, data schemas, and images. We mark the links that must trigger a rebuild and those that can be broken without risk.
- Designing separate pipelines. Each service gets its own set of stages and its own trigger; we move recurring steps into reusable templates so that a new service can be connected with a short description.
- Environment setup. We separate environments, cache, and artifacts so that building one service does not depend on the environment of its neighbors; we grant access on the principle of least privilege.
- Build validation on release. We run the scheme on real releases: parallel builds, rollback to the previous version, behavior when one of the services fails. We make sure that an isolated failure does not stop the others.
- Documentation handover. We provide pipeline schemes, dependency descriptions, the regulation for adding a service and the procedure for changes, and hold a walkthrough with the team. Further maintenance proceeds without our involvement.
What remains in the repository: configurations, schemes, regulations
Infrastructure described only in engineers' heads survives until the first vacation or the author's move to another project.
That is why we capture independent CI/CD pipelines as code in the repository: build descriptions, environment schemes, and regulations sit next to the service and change through review, not by agreement in a chat. After handover, the customer receives a complete set of artifacts.
- Build descriptions. Declarative configurations for each service: stages, dependency cache, trigger conditions. A new service is connected by copying a template, not by setting it up from scratch.
- Environment schemes. What lives where: development, pre-production, and production environments, which branches go into them, where secrets are stored and how they are rotated.
- Access policies. Roles for developers, on-call engineers, and release owners: who starts the build, who deploys to prod, where a second engineer's approval is required.
- Release procedure. The order of steps from test run to production, rollback points, and criteria under which the release stops automatically.
- Instructions for on-call engineers. What to check when a build fails, how to roll a service back to the previous image, whom to escalate to — texts that can be acted on at night without the code author.
- Checklist for connecting a new service. A step-by-step list: which files to add, which policies to extend, how to make sure the new pipeline did not affect neighboring ones.
All of this is stored in the same version control system as the code — the set is updated together with the project rather than becoming outdated separately from it.
Case study: how separate pipelines accelerated releases by 8 times
The client has a Financial service platform of 14 services in one repository. A change in one module triggered the shared pipeline: it built, tested, and published everything, including services the changes did not touch.
The build queue occupied machines for hours, and the release went out as a single package — rolling out one change separately was impossible.
What the metrics showed before
A full run lasted about 48 minutes, and if other teams' builds were ahead in the queue, the wait stretched to 3-4 hours. The release window opened once every two weeks, and an urgent fix waited for it along with the rest.
The share of successful releases stayed at 62%: one broken check in any service blocked the whole package, so the release was rolled back entirely.
What was changed
We split the shared pipeline into independent ones: path-based triggering starts a build only for affected services; tests and artifacts are versioned separately for each. Shared libraries were moved into separate checks that run only when they are modified. We added separate environments and automatic rollback to the service's previous artifact.
The build now completes in 6 minutes, and queue waiting is minutes.
Any service can be released on the day it is ready; the share of successful releases grew to 94%, and recovery after a failure decreased from 40 minutes to 7: rollback affects one service, not the entire platform.
What to do if the pipeline is already assembled into one shared one?
A shared pipeline for all services is a typical growth point: editing one step restarts the build of all repositories, and a failure at a shared stage blocks releases of teams that changed nothing. You cannot rewrite everything at once — that would stop delivery.
That is why the transition is done in layers, and the shared pipeline is kept working until the last service.
First, the base part is extracted from the shared description: dependency installation, checks, artifact publication, deployment templates.
The shared pipeline becomes a thin wrapper over it and continues to build everything as before, while the service file already references the same base.
Build backward compatibility is preserved: artifact names, image tags, and environment variables do not change, so rollback to the previous release remains possible.
Then services are migrated one by one, starting with the one that releases most often and is less coupled to the others. The new independent CI/CD pipeline triggers only on changes in its own repository, while the old one serves the rest.
The first runs go in parallel: artifacts and check results are compared, and discrepancies are investigated before the previous scheme is disabled.
A release freeze is needed locally: changes to the shared part are not made while a service is being switched, otherwise migration and regular changes conflict. At the same time, team delivery is not stopped — the window concerns only the shared plumbing.
Secrets, access to the image registry, and environment permissions are transferred in advance so that the service pipeline receives exactly the same scope of access.
In systems like GitLab CI and similar, the pipeline description resides in the repository, so the transition comes down to moving the file and connecting shared templates, without reworking the build environment.
When the last service is migrated, the shared file is deleted: each service's release no longer depends on its neighbors.
Common technical doubts about separate builds
Independent CI/CD pipelines raise the same engineering questions among customers — not about "can you," but about behavior on their codebase and in their team.
What to do with shared libraries that almost all services depend on?
We publish the shared module as a versioned artifact: a service pins a specific version, not "latest." Updating the library stops being a simultaneous release — each service migrates through its own pipeline when ready; compatibility is maintained by contract tests.
Is a separate test environment needed for each service?
No: base environments are shared, while a temporary one is spun up per branch — it lives from the first commit to merge and deletes itself.
External dependencies are replaced with stubs with documented responses, so checks are reproducible and a queue for a single environment does not form.
Won't build settings diverge across services?
Build, check, and publication steps are moved into reusable templates: a service configuration describes only its differences. A template change applies to all at once, and divergences are visible at merge time, not at release time.
What about support after handover?
We provide configurations, dependency schemes, and the regulation: how to add a step, how to roll back a release, what to do when checks fail. Your engineers go through this on live builds and then change them themselves.
Let's discuss the task: we'll analyze the pipelines and come back with a plan
To come back with a plan for migrating services to independent pipelines rather than general considerations, we need access to your picture of the world: repositories, environments, and an understanding of which services are business-critical.
The analysis takes one meeting; after it, we assemble the scheme and calculate the scope of work for each service.
What we will need from you to start:
- access to repositories — read access to branches, build history, and branch protection rules, so that we can reconstruct the current regulations rather than rewrite them blindly;
- a list of services with priorities — what we migrate first, what is tied to other shared releases and requires an agreed order;
- an environment scheme — how many circuits there are, how their configurations differ, what dependencies on external systems and databases exist;
- a description of the current path from code to production — where the manual steps are now, what checks already exist, and at which stage releases most often break;
- read access to image, configuration, and secret stores — elevated permissions will be granted later, according to an agreed plan and with a time limit;
- a contact person on the development and operations side — with whom to coordinate changes to build rules and the rollback procedure.
Based on the discussion, you will receive a map of pipelines by service, a target environment scheme, and a phased migration plan — from the pilot service to the rest. Describe the task: we will come back with an estimate of the scope of work and a plan.







