CI/CD for micro-frontends: independent pipelines, discovery and rollbacks
Independent deployment is the reason to adopt micro-frontends. If a team cannot take its own change to production without building or releasing anything else, the architecture is not delivering what it costs.
The goal
A team merges a change to its remote. That change reaches production without building, testing or deploying the host or any other remote.
One pipeline per remote
- Build only this remote. In a monorepo, tools such as Nx detect which projects a change affects, so the rest is skipped.
- Test it in isolation: unit tests, component tests, lint.
- Check the contract. Shared dependency versions are within the platform policy, and the exposed modules still exist under the same names.
- Publish immutable artifacts. Upload the build to a versioned path on static hosting or a CDN, for example
/billing/1.42.0/. A published version is never overwritten. - Deploy to a preview or staging environment and run a short smoke test against the composed product.
- Promote. Change the pointer that tells the host which version to load.
- Verify in production with a few automated checks, and roll back automatically if they fail.
Steps 4 and 6 are separate on purpose. Publishing makes a version available. Promoting makes it live.
Discovery: how the host finds remotes
| Approach | How it works | Trade-off |
|---|---|---|
| URLs fixed in the host build | Remote addresses are part of the host's configuration at build time | Simple. Adding or moving a remote needs a host release |
| One stable URL per remote | The host always loads the same address, and each deployment overwrites the file behind it | Simple. Caching must be exact, rollback means redeploying, and it is hard to tell what is live |
| Manifest | At startup the host fetches a small JSON file that maps remote names to versioned URLs | One more moving part. Versions are explicit, rollback is instant, and each environment has its own manifest |
A manifest looks like this:
{
"billing": "https://cdn.example.com/billing/1.42.0/remoteEntry.json",
"catalog": "https://cdn.example.com/catalog/3.7.1/remoteEntry.json"
}
With a manifest, promoting a release means changing one line. That change should go through a controlled step with an audit trail: a pipeline job, or a small service with access control.
Caching rules
- Versioned and hashed files: cache for a long time and mark them immutable.
- The manifest and remote entry files: short cache with revalidation. If these are cached for long, users keep old versions, or receive an entry file that points to chunks that no longer exist.
- Old versions stay available. Users with an open tab keep requesting chunks of the previous version. Keep past artifacts online for days or weeks before cleaning up.
Versioning
- Each remote has its own version. A commit hash in the artifact path or metadata links every file in production to its source.
- The versions that matter across teams are those of the contracts: shared libraries, the design system and the host API. Rules are in Shared dependencies and versions.
- Keep the manifest history. It records which combination of versions was live at any moment, which is the first question in an incident.
Rollbacks
Rolling back means pointing the manifest at the previous version. It takes seconds and needs no build. Three conditions make it work:
- Artifacts are immutable and old versions are retained.
- The backend still accepts requests from the previous frontend version. API changes are additive first, and removals come later.
- A feature that spans several remotes sits behind a feature flag, so releasing it is separate from deploying it.
What the user sees when a remote fails in production is covered in Error isolation and resilience.
Preview environments
A full environment per branch is expensive when the product is ten applications. A lighter pattern works well:
- The pull request pipeline publishes the remote's build under a unique path.
- The reviewer opens the staging host with an override, for example a query parameter, that says "load billing from this path".
- Everything else comes from staging as usual.
An override that loads a remote from an arbitrary URL is a script injection mechanism. Disable it in production, or restrict it to an allowlist of origins and to authorized users.
The same mechanism lets a developer run one remote locally against a deployed host. See Local development with micro-frontends.
The host's pipeline
The host follows the same stages with stricter gates, because its blast radius is the whole product. Before promotion, a smoke test loads every remote listed in the manifest and checks that each one renders. Host releases are less frequent than remote releases, and that is healthy.
Checklist
- Can one team deploy to production without any other pipeline running?
- Are published artifacts immutable and versioned?
- Can you roll back one remote in under a minute, without a build?
- Is the preview override disabled or restricted in production?
More in this section
- Error isolation and resilience in micro-frontends
- Micro-frontend performance: the costs and how to control them
- Testing micro-frontends: a practical strategy
- Monorepo vs polyrepo for micro-frontends
Planning a migration or a micro-frontend platform?
In a 20-minute call you describe your situation and I tell you how I'd approach it. If it isn't worth doing yet, I'll say so.
Message me on LinkedIn