Skip to content

Versioning

In a micro frontend architecture, versioning is how you manage compatibility across independently deployed applications. Each micro frontend evolves on its own schedule; the shell and other consumers must work with multiple versions. This page covers semantic versioning, contract testing, breaking change management, compatibility patterns, and runtime version negotiation.

Micro frontends interact through well-defined interfaces: component props, custom events, shared APIs, or module exports. When one micro frontend changes its interface, consumers may break. With independent deployments, producers and consumers can be out of sync—a new producer version may be deployed before consumers have adapted.

Versioning provides:

  • Compatibility guarantees — Consumers know what to expect
  • Safe evolution — Producers can add and change features without breaking consumers
  • Rollback clarity — When something goes wrong, you know which version was deployed
  • Contract enforcement — Version numbers and contracts align expectations

Semantic Versioning Applied to Micro Frontends

Section titled “Semantic Versioning Applied to Micro Frontends”

Semantic Versioning (SemVer) uses MAJOR.MINOR.PATCH:

  • MAJOR — Breaking changes. Consumers must update to accommodate.
  • MINOR — Backward-compatible additions. Existing consumers continue to work.
  • PATCH — Bug fixes. No interface changes.

For micro frontends:

  • Props interface changes — Removing or renaming a prop is MAJOR. Adding an optional prop is MINOR.
  • Event payload changes — Changing the structure of an emitted event is MAJOR. Adding optional fields is MINOR.
  • API changes — Same rules as for REST or GraphQL APIs.

Teams should maintain a changelog and bump versions according to SemVer. CI can enforce this—e.g., fail the build if a breaking change is detected without a MAJOR bump.

Contract testing ensures that producers and consumers agree on interfaces. It catches incompatibilities before deployment.

  1. Producer defines a contract (e.g., Pact, or a schema for props/events).
  2. Consumer writes tests that verify they can interact with the contract.
  3. CI runs producer contract generation and consumer contract verification. Both must pass.

If the producer changes the contract, consumer tests fail until they are updated. If the producer violates the contract (e.g., forgets to add a field), producer tests fail. This creates a safety net for independent deployments.

  • Pact — Contract testing for HTTP APIs and message queues. Useful for micro frontend backends and BFFs.
  • Custom contracts — For component props, define TypeScript interfaces or JSON Schema. Generate contracts from producer; verify in consumer tests.
  • API schemas — OpenAPI, GraphQL schema. Validate requests/responses against schema in tests.

Breaking changes are inevitable. The goal is to manage them without disrupting production.

How to Evolve Interfaces Without Breaking Consumers

Section titled “How to Evolve Interfaces Without Breaking Consumers”
  1. Add, don’t remove — New optional props, new events, new API fields. Existing consumers ignore them.
  2. Deprecate first — Mark old props/endpoints as deprecated. Log warnings. Give consumers time to migrate.
  3. Support multiple versions — During migration, support both old and new interfaces. Remove the old one after a migration window.
  4. Feature flags — Use flags to gradually roll out breaking changes. New consumers use the new interface; old consumers stay on the old path until migrated.
  • Document — Clearly state deprecation in changelog, docs, and code comments.
  • Warn — Emit console warnings when deprecated APIs are used.
  • Timeline — Announce removal date (e.g., “will be removed in v3.0, scheduled for Q2”).
  • Migration guide — Provide step-by-step instructions for consumers.

Allow time between deprecation and removal. Six months is common for internal consumers; adjust based on team velocity and impact. Coordinate with consumers so they have space in their backlog.

Prefer changes that do not break existing consumers:

  • Add optional parameters
  • Add new optional fields to objects
  • Extend enums with new values (if consumers handle unknowns gracefully)
  • Add new endpoints or components without removing old ones

When backward compatibility is not feasible, use versioning:

  • URL versioning/api/v1/orders, /api/v2/orders
  • Header versioningAccept: application/vnd.myapi.v2+json
  • Export versioningexport { CheckoutV1 } and export { CheckoutV2 } — consumers opt in

Shell or routing layer can decide which version to load based on configuration or feature flags.

Introduce an adapter when you need to support multiple producer versions:

  • Adapter in consumer — Consumer detects producer version and adapts its calls.
  • Adapter in shell — Shell provides a unified interface and adapts to different producer versions.
  • BFF (Backend for Frontend) — A dedicated service translates between consumer expectations and producer APIs.

With Module Federation and similar runtime composition techniques, the shell loads micro frontends at runtime. Version resolution can be automatic or explicit.

Module Federation’s Automatic Version Resolution

Section titled “Module Federation’s Automatic Version Resolution”

Module Federation can resolve shared dependencies at runtime. If the shell expects React 18 and a micro frontend uses React 18, they share one instance. If versions differ, the runtime can load multiple copies or fail with a clear error. Configure requiredVersion and strictVersion to control behavior.

For shared dependencies across micro frontends, see shared dependencies and module federation.

The shell can pin to specific versions of each micro frontend:

{
"checkout": "1.2.3",
"search": "2.0.1"
}

Deploy a new checkout; update the config to "checkout": "1.2.4". The shell loads the specified version. Allows controlled rollouts and quick rollback without redeploying the micro frontend.

Independent versioning — Each micro frontend versions itself. No coordination required. Best for teams that want maximum autonomy. Requires strong contracts and backward compatibility.

Coordinated versioning — Major releases are aligned. All micro frontends bump MAJOR together when the system undergoes a breaking change. Reduces complexity but requires coordination. Use when the system has many interdependencies.

Most organizations start with independent versioning and adopt coordinated approaches only where necessary.

Versioning for micro frontends involves:

  • Semantic versioning for clear compatibility signals
  • Contract testing to keep producers and consumers in sync
  • Breaking change management — deprecate, migrate, then remove
  • API compatibility patterns — backward-compatible changes, versioned endpoints, adapters
  • Runtime version negotiation — Module Federation, explicit pinning, coordinated or independent strategies

For dependency version management in a shared context, see shared dependencies. For runtime composition and version resolution, see module federation. For integrating versioning into pipelines, see CI/CD strategies.

Go Deeper in the Book

This topic is covered in depth in Chapter 8 of Micro Frontends Architecture for Scalable Applications, with detailed examples, diagrams, and production-ready patterns.