Loading content/handbook/engineering/architecture/design-documents/mfe_platform/_index.md 0 → 100644 +128 −0 Changes for content/handbook/engineering/architecture/design-documents/mfe_platform/_index.md: 128 added lines, 0 removed lines. Original line number Diff line number Diff line --- title: "Microfrontend Platform" status: proposed creation-date: "2026-10-07" authors: ["@ntepluhina"] coaches: [] dris: ["@xanf", "@fredericcaplette", "@ntepluhina"] owning-stage: "Plan" participating-stages: [] toc_hide: true --- <!-- vale gitlab.FutureTense = NO --> {{< engineering/design-document-header >}} ## Summary GitLab ships as a monolith behind a single domain (`gitlab.company.com`). Product surfaces such as Duo Chat or Work Items are tightly coupled to the monolith build and release cycle. This design document proposes a micro-frontend (MFE) platform that lets product surfaces be developed, built, versioned, and deployed independently while remaining invisible to the end user: everything stays behind one domain and one login. ## Motivation ### Problems - **Monolith coupling.** Every frontend change, no matter how small, requires a full monolith release. A one-line fix to Duo Chat waits for the same pipeline as a database migration. - **Team coupling.** All teams share one Webpack config, one dependency tree, and one CI pipeline. A broken lint check in one area blocks every deployment. - **No independent versioning.** There is no mechanism to upgrade or downgrade a single product surface. Rollback means rolling back the entire monolith. - **External modules have no UI path.** LabBench modules (separately deployed services) have no standard way to inject UI into the GitLab shell. Each module invents its own integration. ### Goals 1. Product teams can deploy a UI change to their surface without a monolith release. 2. Multiple versions of an MFE can coexist. Upgrade and downgrade are version picks. 3. Self-managed and air-gapped installs receive MFEs through the same release channel they already use. ### Non-Goals - **Single-domain routing (GATE).** The routing layer that puts modules behind one domain is owned by the GATE project and has its own timeline. Until GATE is available, the monolith is configured with the marketplace URL and that origin is added to the CSP. - **Module discovery.** The monolith cannot yet discover which LabBench modules are deployed. The marketplace location is monolith configuration for now. - **Migrating specific product surfaces.** Each surface remains a consumer of the platform and is tracked with its owning team. This document covers the platform, not the migrations. ### Constraints today - **No single domain yet.** Until GATE delivers routing for all deployment types (Omnibus through Kubernetes), the monolith is configured with the marketplace URL and that origin is added to the CSP so MFEs can be embedded from it. - **No module discovery.** The monolith cannot discover which modules are deployed. The marketplace location is monolith configuration, and the manifest must work without discovery. ## Decisions - [ADR 001: Tooling repository strategy](decisions/001_tooling_repository_strategy.md) - Monorepo for tightly coupled tooling, polyrepo for standalone utilities. Also captures the open question of where MFE application code lives. ## Prior art and existing work - [Architecture RFC](https://gitlab.com/gitlab-org/frontend/gitlab-mfe/-/blob/main/docs/architecture-rfc.md) (Rafa Frederico, 2026-04-23): validates Module Federation 2.0 runtime integration with the Webpack 4 host, the `mount`/`unmount` ABI, and same-origin serving. - [Architecture counter-RFC](https://gitlab.com/gitlab-org/frontend/gitlab-mfe/-/blob/main/docs/architecture-counter-rfc.md) (Illya Klymov, 2026-07-12): proposes versioned and integrity-verified delivery, layered contract ownership, rspack as the build tool, and registry-first phasing. Accompanied by a working implementation (!245014). - [Frontend Decomposition design document](../modular_monolith/frontend/_index.md): covers the monolith-side modularization that MFEs consume from outside. - [MFE registry](https://gitlab.com/gitlab-org/frontend/gitlab-mfe-registry): existing prototype for publishing MFE assets to GCS with SHA256 checksums and version manifests. ## Alternative solutions ### Do nothing Product surfaces remain coupled to the monolith release cycle. Teams cannot deploy independently. External modules have no standard UI path. Vue 3 adoption is blocked on a monolith-wide migration. **Pros:** No new infrastructure to build or operate. **Cons:** Coupling cost grows with the number of teams and surfaces. ### iframes Each surface is loaded in an iframe pointed at the module's own domain. **Pros:** Strong isolation. No shared JavaScript scope. **Cons:** Poor UX (no shared navigation, double scrollbars, no shared authentication without postMessage). Accessibility and performance penalties. Does not meet the "one domain" requirement. ### Build-time integration (npm packages) Each surface is published as an npm package and compiled into the monolith Webpack build. **Pros:** No runtime federation overhead. Single build graph. **Cons:** Does not solve independent deployment or rollback. Every surface change still requires a monolith release. Does not help external modules. content/handbook/engineering/architecture/design-documents/mfe_platform/decisions/001_tooling_repository_strategy.md 0 → 100644 +153 −0 Changes for content/handbook/engineering/architecture/design-documents/mfe_platform/decisions/001_tooling_repository_strategy.md: 153 added lines, 0 removed lines. Original line number Diff line number Diff line --- title: "MFE Platform ADR 001: Tooling repository strategy" creation-date: "2026-10-07" authors: ["@ntepluhina"] toc_hide: true --- ## Context The UI Platform team owns shared tooling packages (TypeScript config, ESLint config, Vitest setup, build helpers, publish scripts) and standalone utility libraries (`@gitlab/frontend-utils`, `@gitlab/frontend-tests`). These packages are consumed by the monolith, by LabBench modules that carry their own MFE, and by MFEs that have no module of their own. We need to decide where these packages live on the spectrum between: - **(A) Polyrepo:** each package is its own repository, small and self-contained. - **(B) Monorepo:** a single repository with multiple packages managed via workspaces. This decision is about **tooling packages only**. Where MFE application code lives is a [separate question](001_tooling_repository_strategy.md#mfe-application-code-open). ### Monorepo pros - **Atomic cross-package changes.** A change that touches multiple packages is one MR, not a chain of releases and Renovate bumps. - **Shared CI improvements.** Pipeline configuration, caching, and tooling upgrades happen once and apply to every package. - **Shorter feedback loop.** Changing a shared package immediately surfaces breakage in downstream packages within the same repo. - **Less infrastructure.** No Renovate chains between packages, no project templates, no per-repo CI duplication. - **Discoverability.** Contributors find all tooling in one place instead of searching across repositories. ### Monorepo cons - **CI complexity.** Pipelines need change-detection to avoid running every package's tests on every MR. Tools like Turborepo and Nx help but add their own maintenance cost. - **Maintainer / CODEOWNERS mismatch.** GitLab project maintainers have access to the entire project. CODEOWNERS provides granular approval but not granular merge permissions. - **CODEOWNERS upkeep.** Keeping the CODEOWNERS file correct in a multi-package repo is painful and error-prone. - **Larger agent context.** AI agents need to load more context to understand the repo, though this can be mitigated with per-package AGENTS.md files. ### Polyrepo pros - **Clear boundaries.** Each repo has exactly one owner, one pipeline, one set of maintainers. - **Small surface for agents.** The smaller the repo, the cheaper it is to get an agent up to speed and the more likely it is to propose patterns that match. - **Fast, focused pipelines.** No change-detection logic needed; every push runs the full pipeline and it finishes quickly. - **No permission sprawl.** Maintainer access is scoped to exactly the code that person owns. ### Polyrepo cons - **Renovate chains.** A change in package A that affects package B becomes: release A, Renovate bumps B, release B. Auto-merge reduces the cost but the chain remains. - **CI duplication.** Each repo needs its own pipeline configuration, linting setup, and publish workflow. - **Cross-package testing.** Verifying that a change in one package does not break consumers requires multi-project pipelines or manual testing. ## Decision **Tightly coupled tooling packages** (TypeScript config, ESLint config, Vitest setup, build and publish helpers) go in a **single monorepo** with pnpm workspaces. These packages have strong interdependencies: changes frequently span multiple packages, and the cost of Renovate chains outweighs the CI complexity of a monorepo. **Standalone utility packages** (`@gitlab/frontend-utils`, `@gitlab/frontend-tests` etc.) remain in **separate repositories**. These packages have minimal dependencies on each other, change independently, and gain little from co-location. The polyrepo cons (Renovate chains, cross-package testing) are near zero for these packages. The dividing line: if a package regularly changes together with other packages, it belongs in the monorepo. If it changes independently and has a stable public API consumed by many, it stays standalone. ## Consequences - The UI Platform team creates a single tooling monorepo under `gitlab-org/frontend/` with CODEOWNERS covering each package. - Standalone packages keep their own repositories under the same group. - Both the monorepo and standalone repos follow the same versioning and publishing conventions (changesets, npm publish, Renovate for consumers). --- ## MFE application code (open) Where MFE application code lives is a **separate decision** that has not been made. The constraints differ from tooling: - LabBench modules **must** carry their own MFE in the module's repository. This is polyrepo by construction and the UI Platform team must support it regardless. - MFEs with no module of their own (Duo Chat, Compliance Center) could live in a shared monorepo or in separate repositories. ### Monorepo for MFE apps: pros - Shared infrastructure (federation config, dev proxy, Storybook) is maintained once. - Cross-MFE changes (shared layout, navigation integration) are atomic. - The existing [`gitlab-mfe`](https://gitlab.com/gitlab-org/frontend/gitlab-mfe) repo demonstrates this approach with working CI, Turborepo, and Module Federation. ### Monorepo for MFE apps: cons - The team must support polyrepo anyway (LabBench modules). Maintaining both a monorepo and polyrepo developer experience doubles the infrastructure work. - MFE-specific concerns (bundle size, Vue version drift, security backports) apply to shipped code, unlike dev-time tooling. - An MFE that ships with a module changes together with that module's backend. Putting it in a separate monorepo adds a cross-repo coordination step. ### Polyrepo for MFE apps: pros - Each MFE is owned and released by the team that owns the surface. - Aligns with LabBench's module-per-repo model, so the same tooling works everywhere. - Pipelines are scoped to one MFE; no cross-MFE blast radius. ### Polyrepo for MFE apps: cons - More infrastructure per MFE (CI, federation config, dev proxy). - Cross-MFE changes require coordinated releases. - Discoverability: no single place to see all MFEs. This decision will be revisited once we have more experience with the first MFE deliveries and a clearer picture of how many surfaces will not have a LabBench module. Loading
content/handbook/engineering/architecture/design-documents/mfe_platform/_index.md 0 → 100644 +128 −0 Changes for content/handbook/engineering/architecture/design-documents/mfe_platform/_index.md: 128 added lines, 0 removed lines. Original line number Diff line number Diff line --- title: "Microfrontend Platform" status: proposed creation-date: "2026-10-07" authors: ["@ntepluhina"] coaches: [] dris: ["@xanf", "@fredericcaplette", "@ntepluhina"] owning-stage: "Plan" participating-stages: [] toc_hide: true --- <!-- vale gitlab.FutureTense = NO --> {{< engineering/design-document-header >}} ## Summary GitLab ships as a monolith behind a single domain (`gitlab.company.com`). Product surfaces such as Duo Chat or Work Items are tightly coupled to the monolith build and release cycle. This design document proposes a micro-frontend (MFE) platform that lets product surfaces be developed, built, versioned, and deployed independently while remaining invisible to the end user: everything stays behind one domain and one login. ## Motivation ### Problems - **Monolith coupling.** Every frontend change, no matter how small, requires a full monolith release. A one-line fix to Duo Chat waits for the same pipeline as a database migration. - **Team coupling.** All teams share one Webpack config, one dependency tree, and one CI pipeline. A broken lint check in one area blocks every deployment. - **No independent versioning.** There is no mechanism to upgrade or downgrade a single product surface. Rollback means rolling back the entire monolith. - **External modules have no UI path.** LabBench modules (separately deployed services) have no standard way to inject UI into the GitLab shell. Each module invents its own integration. ### Goals 1. Product teams can deploy a UI change to their surface without a monolith release. 2. Multiple versions of an MFE can coexist. Upgrade and downgrade are version picks. 3. Self-managed and air-gapped installs receive MFEs through the same release channel they already use. ### Non-Goals - **Single-domain routing (GATE).** The routing layer that puts modules behind one domain is owned by the GATE project and has its own timeline. Until GATE is available, the monolith is configured with the marketplace URL and that origin is added to the CSP. - **Module discovery.** The monolith cannot yet discover which LabBench modules are deployed. The marketplace location is monolith configuration for now. - **Migrating specific product surfaces.** Each surface remains a consumer of the platform and is tracked with its owning team. This document covers the platform, not the migrations. ### Constraints today - **No single domain yet.** Until GATE delivers routing for all deployment types (Omnibus through Kubernetes), the monolith is configured with the marketplace URL and that origin is added to the CSP so MFEs can be embedded from it. - **No module discovery.** The monolith cannot discover which modules are deployed. The marketplace location is monolith configuration, and the manifest must work without discovery. ## Decisions - [ADR 001: Tooling repository strategy](decisions/001_tooling_repository_strategy.md) - Monorepo for tightly coupled tooling, polyrepo for standalone utilities. Also captures the open question of where MFE application code lives. ## Prior art and existing work - [Architecture RFC](https://gitlab.com/gitlab-org/frontend/gitlab-mfe/-/blob/main/docs/architecture-rfc.md) (Rafa Frederico, 2026-04-23): validates Module Federation 2.0 runtime integration with the Webpack 4 host, the `mount`/`unmount` ABI, and same-origin serving. - [Architecture counter-RFC](https://gitlab.com/gitlab-org/frontend/gitlab-mfe/-/blob/main/docs/architecture-counter-rfc.md) (Illya Klymov, 2026-07-12): proposes versioned and integrity-verified delivery, layered contract ownership, rspack as the build tool, and registry-first phasing. Accompanied by a working implementation (!245014). - [Frontend Decomposition design document](../modular_monolith/frontend/_index.md): covers the monolith-side modularization that MFEs consume from outside. - [MFE registry](https://gitlab.com/gitlab-org/frontend/gitlab-mfe-registry): existing prototype for publishing MFE assets to GCS with SHA256 checksums and version manifests. ## Alternative solutions ### Do nothing Product surfaces remain coupled to the monolith release cycle. Teams cannot deploy independently. External modules have no standard UI path. Vue 3 adoption is blocked on a monolith-wide migration. **Pros:** No new infrastructure to build or operate. **Cons:** Coupling cost grows with the number of teams and surfaces. ### iframes Each surface is loaded in an iframe pointed at the module's own domain. **Pros:** Strong isolation. No shared JavaScript scope. **Cons:** Poor UX (no shared navigation, double scrollbars, no shared authentication without postMessage). Accessibility and performance penalties. Does not meet the "one domain" requirement. ### Build-time integration (npm packages) Each surface is published as an npm package and compiled into the monolith Webpack build. **Pros:** No runtime federation overhead. Single build graph. **Cons:** Does not solve independent deployment or rollback. Every surface change still requires a monolith release. Does not help external modules.
content/handbook/engineering/architecture/design-documents/mfe_platform/decisions/001_tooling_repository_strategy.md 0 → 100644 +153 −0 Changes for content/handbook/engineering/architecture/design-documents/mfe_platform/decisions/001_tooling_repository_strategy.md: 153 added lines, 0 removed lines. Original line number Diff line number Diff line --- title: "MFE Platform ADR 001: Tooling repository strategy" creation-date: "2026-10-07" authors: ["@ntepluhina"] toc_hide: true --- ## Context The UI Platform team owns shared tooling packages (TypeScript config, ESLint config, Vitest setup, build helpers, publish scripts) and standalone utility libraries (`@gitlab/frontend-utils`, `@gitlab/frontend-tests`). These packages are consumed by the monolith, by LabBench modules that carry their own MFE, and by MFEs that have no module of their own. We need to decide where these packages live on the spectrum between: - **(A) Polyrepo:** each package is its own repository, small and self-contained. - **(B) Monorepo:** a single repository with multiple packages managed via workspaces. This decision is about **tooling packages only**. Where MFE application code lives is a [separate question](001_tooling_repository_strategy.md#mfe-application-code-open). ### Monorepo pros - **Atomic cross-package changes.** A change that touches multiple packages is one MR, not a chain of releases and Renovate bumps. - **Shared CI improvements.** Pipeline configuration, caching, and tooling upgrades happen once and apply to every package. - **Shorter feedback loop.** Changing a shared package immediately surfaces breakage in downstream packages within the same repo. - **Less infrastructure.** No Renovate chains between packages, no project templates, no per-repo CI duplication. - **Discoverability.** Contributors find all tooling in one place instead of searching across repositories. ### Monorepo cons - **CI complexity.** Pipelines need change-detection to avoid running every package's tests on every MR. Tools like Turborepo and Nx help but add their own maintenance cost. - **Maintainer / CODEOWNERS mismatch.** GitLab project maintainers have access to the entire project. CODEOWNERS provides granular approval but not granular merge permissions. - **CODEOWNERS upkeep.** Keeping the CODEOWNERS file correct in a multi-package repo is painful and error-prone. - **Larger agent context.** AI agents need to load more context to understand the repo, though this can be mitigated with per-package AGENTS.md files. ### Polyrepo pros - **Clear boundaries.** Each repo has exactly one owner, one pipeline, one set of maintainers. - **Small surface for agents.** The smaller the repo, the cheaper it is to get an agent up to speed and the more likely it is to propose patterns that match. - **Fast, focused pipelines.** No change-detection logic needed; every push runs the full pipeline and it finishes quickly. - **No permission sprawl.** Maintainer access is scoped to exactly the code that person owns. ### Polyrepo cons - **Renovate chains.** A change in package A that affects package B becomes: release A, Renovate bumps B, release B. Auto-merge reduces the cost but the chain remains. - **CI duplication.** Each repo needs its own pipeline configuration, linting setup, and publish workflow. - **Cross-package testing.** Verifying that a change in one package does not break consumers requires multi-project pipelines or manual testing. ## Decision **Tightly coupled tooling packages** (TypeScript config, ESLint config, Vitest setup, build and publish helpers) go in a **single monorepo** with pnpm workspaces. These packages have strong interdependencies: changes frequently span multiple packages, and the cost of Renovate chains outweighs the CI complexity of a monorepo. **Standalone utility packages** (`@gitlab/frontend-utils`, `@gitlab/frontend-tests` etc.) remain in **separate repositories**. These packages have minimal dependencies on each other, change independently, and gain little from co-location. The polyrepo cons (Renovate chains, cross-package testing) are near zero for these packages. The dividing line: if a package regularly changes together with other packages, it belongs in the monorepo. If it changes independently and has a stable public API consumed by many, it stays standalone. ## Consequences - The UI Platform team creates a single tooling monorepo under `gitlab-org/frontend/` with CODEOWNERS covering each package. - Standalone packages keep their own repositories under the same group. - Both the monorepo and standalone repos follow the same versioning and publishing conventions (changesets, npm publish, Renovate for consumers). --- ## MFE application code (open) Where MFE application code lives is a **separate decision** that has not been made. The constraints differ from tooling: - LabBench modules **must** carry their own MFE in the module's repository. This is polyrepo by construction and the UI Platform team must support it regardless. - MFEs with no module of their own (Duo Chat, Compliance Center) could live in a shared monorepo or in separate repositories. ### Monorepo for MFE apps: pros - Shared infrastructure (federation config, dev proxy, Storybook) is maintained once. - Cross-MFE changes (shared layout, navigation integration) are atomic. - The existing [`gitlab-mfe`](https://gitlab.com/gitlab-org/frontend/gitlab-mfe) repo demonstrates this approach with working CI, Turborepo, and Module Federation. ### Monorepo for MFE apps: cons - The team must support polyrepo anyway (LabBench modules). Maintaining both a monorepo and polyrepo developer experience doubles the infrastructure work. - MFE-specific concerns (bundle size, Vue version drift, security backports) apply to shipped code, unlike dev-time tooling. - An MFE that ships with a module changes together with that module's backend. Putting it in a separate monorepo adds a cross-repo coordination step. ### Polyrepo for MFE apps: pros - Each MFE is owned and released by the team that owns the surface. - Aligns with LabBench's module-per-repo model, so the same tooling works everywhere. - Pipelines are scoped to one MFE; no cross-MFE blast radius. ### Polyrepo for MFE apps: cons - More infrastructure per MFE (CI, federation config, dev proxy). - Cross-MFE changes require coordinated releases. - Discoverability: no single place to see all MFEs. This decision will be revisited once we have more experience with the first MFE deliveries and a clearer picture of how many surfaces will not have a LabBench module.