skip to content

Several teams each run their own CI/CD pipeline and deploy their microfrontend to production independently of the others, with no shared release train. What must the integration contract guarantee for that independence to be safe, and what specifically goes wrong if a team violates it mid-deploy?

level: middleimportance: must knowfreq 60%

answer

  1. backward compatibility at all times
  2. no simultaneous-deploy guarantee
  3. additive = safe, removal/rename = breaking
  4. failure surfaces in someone else's fragment
  5. same discipline as backend API versioning

basics

~20 s

Every deploy must keep working with old and new versions of everyone else at the same time, because you never know exactly who's running what. If a team ships a change that only works with a version nobody else has deployed yet, things break for real users mid-rollout.

solid answer

~50 s

Independent CI/CD only works safely if every deploy is backward-compatible with the contract version currently live everywhere else — because at any moment during a rolling deploy, users may be served an old shell alongside a new fragment, or vice versa, and there's no coordination point to guarantee otherwise. This means additive changes (new optional props, new event fields) are safe to ship any time, but changes that remove or repurpose an existing prop/event field are breaking and require either a deprecation window (support both shapes concurrently) or a major-version bump that consumers opt into deliberately. Violating this — shipping a breaking contract change straight to production — causes runtime failures that are hard to trace because the failure surfaces in a different team's fragment, deployed at a different time, often reported by users rather than caught in that team's own tests.

go deeper

for a junior

Understands that teams deploy separately and can articulate, in plain terms, that 'if you change something another team depends on, it can break them without warning.'

for a middle

Can distinguish additive vs. breaking changes and explain why the deploying team's own tests can't catch cross-team breakage.

for a senior

Reasons explicitly about the rolling-deploy window (old and new versions coexisting) and proposes concrete mitigations like deprecation windows or contract tests.

for a principal

Frames this as the same distributed-systems compatibility problem backend teams solve with API versioning, and can design the org-wide tooling/process (contract testing pipelines, canary policies) that makes it safe at scale.

## What independent CI/CD buys Independent CI/CD means each microfrontend team can push a change to production the moment it passes their own tests, without waiting on any other team's schedule, sign-off, or release train. That's the operational payoff of the whole architecture — a checkout team can ship a bug fix in an hour instead of waiting for a company-wide Tuesday release. But it only stays safe under one condition: every deploy must be compatible with whatever contract version every other fragment currently in production is using, because there is no moment in time when you can guarantee all teams are on "the latest" of everything simultaneously. ## Why this is a distributed-systems problem Concretely, this is a distributed-systems compatibility problem, not just a frontend one. - During any team's rollout — even a fast one — there's a window where some users hit the old version of that fragment and some hit the new one (canary, blue-green, or just CDN cache staggering). - Simultaneously, every *other* fragment in the system is running whatever version was last deployed, on its own independent schedule, possibly months old. - So a new deploy of fragment A must work correctly against both the currently-deployed and the previous version of fragment B's contract, and vice versa — there's no "deploy everything together" escape hatch. This is exactly the same compatibility discipline that backend teams apply to REST/event APIs between independently deployed services; microfrontends just move that same discipline into the browser. ## Additive versus breaking changes The practical rule that follows is: **additive, backward-compatible changes are always safe to ship unilaterally** — - adding a new optional prop with a sensible default, - adding a new field to an event payload that old consumers simply ignore, - adding a new custom event nobody currently listens for. Changes that are *not* backward-compatible — removing a prop, renaming an existing field, changing a field's type or meaning, changing what an event means — require a deliberate migration path: - either the producing team supports both the old and new shape simultaneously for a deprecation window (e.g. emitting both `total` and `totalAmount` for a few weeks, with a warning log on the old field), - or the change is gated behind an explicit contract version that consuming teams must opt into (feature-detect the field, or pin/bump a declared dependency version), never a silent flip that every currently-deployed consumer is forced into instantly. ## What a violation feels like When a team violates this — ships a breaking change as if it were a normal deploy — the failure mode is distinctively painful compared to a monolith bug. - The error doesn't surface in the deploying team's own CI, tests, or even their own fragment; it surfaces at runtime, in a *different* team's fragment, for users who happen to load both fragments' current versions together, often hours or days after the deploy went out (because CDN caching and staggered rollout mean the blast radius grows gradually). - The on-call engineer paged is frequently on a team that changed nothing, debugging a stack trace that terminates in another team's code they don't own and may not have read access to. - Root-causing this requires correlating deploy timestamps across pipelines that don't share a dashboard, which is exactly the coordination tax the architecture was supposed to eliminate. ## Where the discipline is already practised A well-known real-world instance of this discipline is how teams using Webpack Module Federation manage shared/exposed modules: a "remote" app that exposes a component or event contract is expected to treat that exposed surface like a public package API — semantic versioning, deprecation notices, changelogs — precisely because the "host" apps consuming it deploy on unrelated schedules and there's no build-time linkage forcing them to update together. Platforms operating at scale with many independently-deployed frontend teams (e.g. large e-commerce or media companies running dozens of fragments) invest specifically in contract testing (see the related follow-up on consumer-driven contracts) and staged/canary rollouts for shared contract changes, because the cost of a breaking change discovered in production, across team boundaries, in a live customer-facing checkout or account flow, is high enough to justify the tooling investment. The core takeaway: independent CI/CD trades coordination overhead for compatibility discipline — you don't eliminate the need for careful change management, you just move it from "a release manager blocks your deploy" to "your contract must be provably backward-compatible before you're allowed to ship it alone."

  • How would you detect a breaking contract change before it reaches production, given that each team's CI can't see the other teams' code?
    Consumer-driven contract testing: each consumer publishes an executable specification of what it expects from the contract (a set of assertions on prop shapes or event payloads), and the producer's CI runs those consumer-supplied checks against its own build before deploy, failing fast if a breaking change would violate any known consumer's expectations. This catches the class of breakage that unit tests within a single team's repo structurally cannot see.
  • If a team must make a breaking change (e.g. an event field's meaning fundamentally changes), what's a safe rollout pattern?
    Dual-write/dual-emit for a deprecation window: emit both the old and new event shapes (or accept both old and new prop shapes) simultaneously, log usage of the old shape so you can see when it's safe to remove, announce a removal date to known consumers, and only drop the old shape after telemetry shows no one is still relying on it.

It's like several airlines sharing one runway and radio frequency but scheduling flights independently — every pilot must follow the same, unchanging radio protocol at all times, because you can never coordinate 'everyone switch protocols at 3pm' across airlines that don't share a scheduling office.

saying these in an interview costs you the question

  • Assumes all teams' deploys can be coordinated to happen 'at the same time'
  • Doesn't recognize that a breaking change can be live for old AND new consumers simultaneously during rollout
  • Suggests the fix is 'just deploy everything together' — reintroducing a release train
  • No concept of additive vs. breaking change as the deciding factor for safety
  • Assumes their own team's CI passing means the change is safe for the whole system

context