CI/CD Course
CI/CD for Monolithic Applications
In this lesson
CI/CD for monolithic applications is the practice of applying modern delivery pipeline discipline — fast feedback, automated verification, frequent deployment — to applications where every component is packaged and deployed as a single unit. The monolith is not an architectural failure to be immediately decomposed; it is a valid, widely used architecture that presents its own distinct CI/CD challenges. Build times are longer because the entire application must compile. Test suites are larger because the entire domain must be covered. Deployments are higher-risk because the entire application is replaced in one operation. The goal of CI/CD for monoliths is to manage these characteristics — not to eliminate the monolith.
The Specific Challenges of Monolith Pipelines
A monolith pipeline faces challenges that do not exist at the same scale in microservices pipelines. Understanding them is the prerequisite for addressing them effectively rather than treating them as inherent limitations of the architecture.
Monolith Pipeline Challenges and Their Solutions
The Ocean Liner Analogy
Turning an ocean liner takes more time and distance than turning a speedboat. That is not a flaw — it is physics, and the liner carries far more cargo. The challenge is not to make the liner turn like a speedboat; it is to plan turns far enough in advance, execute them smoothly, and not overcorrect. CI/CD for monoliths works the same way: the pipeline takes longer than a microservices pipeline, deployments require more care, and tests cover more ground. The solution is not to pretend these properties do not exist — it is to design pipeline architecture that accommodates them gracefully: good caching, aggressive parallelism, small frequent deployments, and zero-downtime deployment strategies.
Parallel Test Execution — The Most Impactful Speed Lever
For a monolith with a large test suite, parallelisation is the single most impactful pipeline performance improvement available. GitHub Actions supports job-level parallelism natively — the same test suite can be split across multiple runners, each running a different subset, with the total test time collapsing from the sum of all tests to the duration of the slowest parallel shard.
Parallelised Test Suite — GitHub Actions Matrix Strategy
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
shard: [1, 2, 3, 4, 5] # Split tests across 5 parallel runners
fail-fast: true # Cancel remaining shards if one fails
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- name: Run test shard
run: |
npx jest \
--shard=${{ matrix.shard }}/5 \ # This runner handles 1/5 of the test suite
--forceExit \
--coverage
# Jest splits tests by file count across shards automatically
# A 40-minute suite becomes ~8 minutes across 5 parallel runners
all-tests-passed:
needs: test # Gates the deploy on all shards passing
runs-on: ubuntu-latest
steps:
- run: echo "All test shards passed — safe to deploy"
What just happened?
Five runners execute simultaneously, each handling one fifth of the test suite. A suite that previously took 40 minutes now completes in approximately 8. The fail-fast option cancels remaining shards immediately if any shard fails — no point running the other 80% of tests if we already know the build is broken. A gate job ensures the deploy stage only proceeds when every shard has passed.
Deployment Strategies for Zero-Downtime Monolith Releases
Deploying a monolith does not have to mean downtime. Two strategies make monolith deployments zero-downtime while preserving fast rollback capability: blue-green deployment and rolling deployment. Both are covered in more depth in Lesson 33, but their application to monoliths is worth highlighting specifically here.
Blue-green deployment maintains two identical production environments — blue (current) and green (next). The new version is deployed to the green environment and smoke tested there before any traffic is switched. When ready, a load balancer cutover moves all traffic from blue to green in seconds. Rollback is equally fast: switch traffic back to blue. The previous version is still running and ready to serve. For a monolith where a deployment touches every component, the ability to test the complete deployed version before it receives production traffic — and to roll back instantly without redeploying — is particularly valuable.
The Strangler Fig Pattern — Evolving Toward Services
Many organisations with monoliths eventually reach a point where parts of the system would benefit from being extracted into independent services — not because monoliths are wrong, but because specific domains have grown to a size where independent deployability and team ownership would accelerate delivery. The strangler fig pattern describes this evolution: new functionality is built as separate services, a routing layer (often an API gateway or reverse proxy) directs traffic to either the monolith or the new service, and over time the monolith's surface area shrinks as more functionality is extracted.
From a CI/CD perspective, the strangler fig pattern introduces a mixed architecture that requires pipeline coordination between the monolith pipeline and the emerging service pipelines. The routing layer must be versioned and deployed alongside the service changes. Contract tests between the monolith and new services catch integration regressions. Feature flags control which requests go to the monolith versus the new service, enabling gradual traffic migration without a hard cutover. The pipeline architecture must evolve alongside the application architecture — neither can lead the other too far without creating a gap that causes incidents.
Warning: Large Infrequent Deployments Are the Biggest Risk in Monolith CI/CD
The most dangerous monolith deployment pattern is the one that accumulates weeks of changes into a large batch release. Each change in isolation may be low-risk, but twenty changes deployed simultaneously produce an aggregate risk that is orders of magnitude higher — more code changed, more potential interactions, harder to identify the culprit when something fails, and a longer fix cycle because every possible change must be investigated. The solution is not to deploy less frequently; it is to deploy more frequently and in smaller batches. A monolith that deploys daily with five changes per release is dramatically safer than one that deploys monthly with a hundred changes. CI/CD discipline applied to a monolith achieves exactly this — small, frequent, verified deployments that keep batch size small and rollback scope narrow.
Key Takeaways from This Lesson
Teacher's Note
Before decomposing a monolith into microservices, measure how often you deploy it and how long each deployment takes — if the answer is "infrequently and nervously," fixing the CI/CD pipeline almost always delivers more value faster than an architectural rewrite.
Practice Questions
Answer in your own words — then check against the expected answer.
1. What is the name of the architectural pattern — named after a tree that grows around and gradually replaces its host — that describes extracting microservices from a monolith incrementally, routing traffic to either the monolith or the new service via a proxy layer while the monolith's surface area shrinks over time?
2. What is the technique — supported by test runners like Jest via the --shard flag — that splits a test suite across multiple parallel runners, each executing a distinct subset, so that total test time equals the duration of the slowest subset rather than the sum of all tests?
3. What deployment strategy maintains two identical production environments — one running the current version and one receiving the new version — allowing the new version to be fully smoke tested before a load balancer cutover, with rollback achieved by switching traffic back rather than redeploying?
Lesson Quiz
1. A monolith has a test suite that takes 40 minutes to run serially. Developers have stopped waiting for pipeline results before pushing follow-up commits. What single pipeline architecture change would have the most immediate impact on feedback loop speed?
2. Team A deploys their monolith weekly with an average of five changes per release. Team B deploys monthly with an average of twenty changes per release. Both teams have equivalent test coverage. Which team has lower deployment risk, and why?
3. A team wants to begin extracting services from their monolith without stopping feature development or committing to a full rewrite. What pattern allows them to build new functionality outside the monolith while keeping the existing application running, migrating traffic gradually as each extracted service stabilises?
Up Next · Lesson 33
Blue-Green Deployments
Lesson 32 introduced blue-green as a monolith deployment strategy. Lesson 33 goes deep — the full mechanics, the pipeline implementation, the database considerations, and when blue-green is and is not the right choice.