
Citadel Cloud Management
Microservices Communication Patterns
DevOps PipelinesCreated by Kenny Ogunlowo
Product Description
Microservices Communication Patterns
Monorepo CI without path filtering is a tax on every developer. At one enterprise I consulted for, a single character change in a README triggered a 45-minute build across 12 services because their pipeline did not differentiate which package changed. Developers started pushing directly to main to skip the queue. The pipeline that was supposed to protect quality became the reason quality degraded. This template uses path-based triggering, dependency-aware builds, and parallelized service pipelines that only build what changed.
Built from monorepo pipelines I have operated at enterprise scale with 20+ services in a single repository, this workflow handles Nx, Turborepo, Lerna, and custom workspace configurations with intelligent change detection.
Pipeline Stages
-
change-detection —
dorny/paths-filter@v3analyzes the git diff to determine which workspace packages changed. Outputs a JSON matrix of affected packages that downstream jobs consume. Dependency graph analysis ensures that ifshared-utilschanges, all packages that import it are also rebuilt. -
lint-affected — Runs linters only on changed packages.
npx nx affected --target=lintornpx turbo run lint --filter=...[HEAD~1]. Caches lint results withactions/cache@v4keyed on file hash. -
test-affected — Parallel test execution across affected packages. Each package runs in its own job via
strategy.matrixpopulated from the change detection output. Shared service containers (database, cache) are provisioned per job. -
build-affected — Builds only changed packages and their dependents. Docker images are built with package-specific Dockerfiles. Build cache shared across PRs via
actions/cache@v4with the lockfile hash as key. - deploy-affected — Deploys only the services that changed. Each service has its own deployment job with environment-specific gates. Services that did not change are not redeployed, reducing blast radius.
- integration-test — Cross-service integration tests run only when inter-service contracts change. Contract changes trigger tests for both the producer and all consumer services.
Security Gates
-
Per-package CODEOWNERS — Each workspace package has a CODEOWNERS entry. Changes to
packages/auth/require security team review. Changes topackages/billing/require finance team review. -
Dependency isolation — Package-level lockfiles prevent a dependency update in one service from affecting another.
actions/dependency-review-action@v4scans per-package dependency changes. - Scoped deployment credentials — Each service has its own deployment IAM role. The auth service deployer cannot access the billing service's database credentials.
Environment Matrix
Dev deploys affected services on merge to develop. Staging deploys on release candidate tags. Production deploys individual services with independent approval gates — the auth service can deploy without waiting for the billing service approval. Each service maintains its own semantic version.
Top 3 Failures
-
Transitive dependency change missed — Package A depends on Package B which depends on Package C. A change in C is not detected as affecting A because the dependency graph only has direct edges. Fix: use
nx affectedor build a dependency graph from lockfile resolution that includes transitive dependencies. -
Cache poisoning from branch merges — A feature branch caches a broken build artifact, then the main branch restores that cache. Fix: use
restore-keyshierarchy: exact key first, then branch-specific prefix, then main branch fallback. Never share caches from feature branches to main. -
GitHub Actions matrix limit — More than 256 jobs in a matrix causes the workflow to fail. Fix: batch packages into groups of 10-20 and run them as sequential waves, or split into multiple workflow files with
workflow_calltriggers.