A practical pattern for monorepo CI with path filters, matrix builds, caching, and deployment guards that keep feedback fast as teams scale.
Monorepos improve shared ownership and cross-service refactoring, but CI pipelines can become slow and expensive when every pull request runs every job. The fix is not one giant workflow file. The fix is a clear build contract with targeted execution, predictable caching, and strict release gates.
Use three layers:
name: ci
on:
pull_request:
push:
branches: [main]
jobs:
detect:
runs-on: ubuntu-latest
outputs:
services: ${{ steps.set.outputs.services }}
steps:
- uses: actions/checkout@v4
- id: set
run: |
CHANGED=$(git diff --name-only origin/main...HEAD | cut -d/ -f1,2 | sort -u)
SERVICES=$(echo "$CHANGED" | grep '^services/' | cut -d/ -f2 | jq -R -s -c 'split("\n")[:-1]')
echo "services=$SERVICES" >> $GITHUB_OUTPUT
This keeps you from building unrelated applications when docs or other folders change.
test:
needs: detect
if: ${{ needs.detect.outputs.services != '[]' }}
strategy:
matrix:
service: ${{ fromJson(needs.detect.outputs.services) }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run lint --workspace=services/${{ matrix.service }}
- run: npm run test --workspace=services/${{ matrix.service }}
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
Pair this with protected environments and manual approvals for production.
With this model, monorepo CI stays fast as service count grows.
Get the latest tutorials, guides, and insights on AI, DevOps, Cloud, and Infrastructure delivered directly to your inbox.
A production-focused guide to Azure DevOps: standardized YAML templates, secure service connections, rollout safety, and measurable delivery reliability.
How to implement Backstage with real templates, scorecards, and golden paths so internal platform work reduces delivery friction.
Explore more articles in this category
Production monitoring catches user-facing issues. CI failures stay invisible until someone notices the merge queue is stuck. The metrics and alerts that make pipelines observable.
Static thresholds on error rate produce noisy alerts. Burn-rate alerting flips the question to "are we burning the error budget faster than we can sustain?" — and pages only on real problems.
SBOMs and signed attestations sound like checkboxes until you need to answer "did this artifact come from our pipeline?" The minimum viable supply-chain story we run.
Evergreen posts worth revisiting.