When a platform team defines a route table like `/checkout/* -> checkout-team`, `/search/* -> search-team`, `/account/* -> account-team` for a microfrontend shell, what problem does this mapping solve, and what happens when two teams need to render content on the same URL segment (e.g. a global site-wide header that appears on every path)?
answer
- route table = path pattern -> owning team/MFE
- prefix trie enforceable at CDN too
- shared chrome mounted once, not per-route
- composition/slot for cross-team page pieces
- overlap detection via manifest/CI
basics
~20 sThe mapping tells the shell which team's code to load for a given URL, so each team can build and deploy independently. Shared elements like a global header that appear on every page are usually owned by a separate, always-mounted piece rather than by any single route-owning team.
solid answer
~40 sThe route table is the technical expression of an organizational decision: which team owns which URL space, and therefore which team can deploy changes to that experience without coordinating with others. It works cleanly when routes are a strict tree with non-overlapping prefixes matching team boundaries. It breaks down for content that spans multiple routes — a global header/nav, a notifications bell, a footer — because those aren't 'owned' by any single route; the standard solution is to carve them out as separate, persistently-mounted microfrontends ('always-on' or 'shell-level') that the shell mounts once at startup rather than per-route, with their own ownership and deploy cadence independent of the route table.
go deeper
Should understand that a route table maps URL prefixes to which team's code renders, and that shared elements like headers are usually separate from any one team's routes.
Should explain the tree/prefix model, why it grants deploy independence, and describe the shared-chrome pattern (mounted once, not per-route).
Should identify overlap/collision risk in the route table as a real production hazard and know at least one resolution pattern (composition vs sub-delegation) for cross-team page needs.
Should discuss governance: treating the route table as a reviewed, versioned artifact with automated overlap detection, and the organizational design (Conway's Law) implications of how route boundaries are drawn relative to team boundaries.
## From an organizational decision to a route table Mapping URL path segments to microfrontend ownership is the mechanism that turns a business/organizational decision — 'the checkout team owns the checkout experience' — into an enforceable technical structure. Concretely, the shell maintains a **route table**: an ordered or trie-like data structure of path patterns (`/checkout/*`, `/search/*`, `/account/*`) each associated with: - a microfrontend to load - its JS entry point/manifest URL - and often metadata like the owning team, on-call contact, and repository When the shell's router resolves the current URL against this table, it isn't just deciding what UI to render — it's enforcing a boundary: only the checkout team's deployed artifact can serve requests under `/checkout/*`, and any change to that experience is a deploy of checkout-team's own pipeline, requiring no coordination with the search or account teams. ## What the mapping solves This solves several real problems simultaneously. 1. **First**, it gives teams true deployment independence: a route-table-driven shell can be configured (often via a manifest fetched at runtime, e.g. an import map or a JSON route manifest) so that deploying a new version of the checkout microfrontend is just publishing new JS/asset URLs and updating the manifest entry — no shell redeploy, no coordination with other teams' release trains. 2. **Second**, it gives a scalable mental model for large orgs: instead of one team's PR touching a monolithic frontend's shared router config (a common source of merge conflicts and cross-team review bottlenecks), each team's route ownership is a contract, and route-table changes are themselves reviewable, attributable changes. 3. **Third**, at the infrastructure layer, path-based ownership can be enforced even below the shell — a reverse proxy or CDN can route `/checkout/*` requests to entirely different origins/servers per team, so ownership isn't just a client-side convention but a network-level guarantee, useful for independent SSR, independent scaling, or even different tech stacks per team. ## Where the clean model breaks — shared chrome The clean version of this model assumes URL space partitions like a tree with non-overlapping prefixes matching team boundaries one-to-one. Reality rarely cooperates. The first common break is **shared chrome**: - a global header with the logo, primary nav, and a notification bell - a footer - a cookie-consent banner None of these 'belong' to any single route — they need to appear on `/checkout/*` and `/search/*` and everywhere else simultaneously. The standard resolution is to model them as separate, persistently-mounted microfrontends that the shell mounts once at application bootstrap (outside the route-table lifecycle) rather than mounting/unmounting per route transition — sometimes called 'always-on' or 'shell-chrome' microfrontends. They have their own team ownership, their own deploy pipeline, and their own (usually much smaller) routing concerns (e.g. the header might need to know the current route to highlight the active nav item, meaning it has to observe the shell's router state without owning navigation decisions). ## When one page needs pieces from two teams The second common break is when a single conceptual 'page' needs pieces from two teams — e.g. a product page primarily owned by the catalog team but needing an inline 'Add to cart' widget owned by the cart team. Two established patterns handle this: - **composition** — the catalog team's page includes a slot/mount-point and asynchronously loads the cart team's widget component into it via a well-defined contract — props in, events out — without the cart team owning any route - **route sub-delegation** — the catalog team's route boundary is `/products/*`, and within that boundary the catalog team's own internal router further delegates specific interactive regions, not routes, to other teams' exposed components What's important is that only one team ever owns routing decisions for a URL — the ownership ambiguity is resolved at the component-composition level, not by two teams both trying to register overlapping route patterns, which produces non-deterministic 'whichever route matcher runs first wins' bugs. ## The route table as a governed artifact A concrete real-world pattern: mature microfrontend platforms, as documented in public engineering talks (e.g. from IKEA and Spotify), use a route-ownership manifest checked into a central registry, with tooling that fails CI if two teams' declared route patterns overlap, precisely because an undetected overlap either silently favors whichever microfrontend's manifest was registered/loaded last, or produces flicker as both mount and immediately unmount each other. This is why mature platforms treat the route table itself as a governed artifact — versioned, reviewed, and validated for non-overlap — rather than a loose convention teams self-police.
- Why is it dangerous for two teams' route patterns to overlap in the shell's route table (e.g. both `/account/*` and `/account/billing/*` mapped to different microfrontends)?Whichever pattern the router evaluates or matches first wins, so the outcome depends on route-table ordering or manifest load order rather than explicit intent — a subtle change elsewhere can silently redirect traffic from one team's microfrontend to another's. It's effectively a race condition baked into configuration rather than runtime code.
- How would you handle a global notification bell that needs to show a live unread count regardless of which route-owned microfrontend is currently mounted?Mount it as a persistent, always-on microfrontend at the shell level (outside the per-route mount/unmount cycle) so it survives route transitions, and have it get its data from a shared store or its own API polling/websocket rather than depending on whichever route-microfrontend happens to be active.
- What's the difference between resolving a shared-content need through composition versus through route sub-delegation?Composition means one team's page includes a slot and loads another team's exposed component into it, with the composing team still owning the route and orchestrating layout. Route sub-delegation means the owning team's own internal router further splits its owned URL space into sub-paths, but that team still owns all the routing decisions within its boundary — no other team registers a competing route pattern.
It's like assigning shop units along a mall corridor to different retailers by unit number — each retailer fully controls their own storefront, but the mall's shared corridor lighting and directory sign aren't owned by any one shop and are maintained by mall management instead.
saying these in an interview costs you the question
- Thinks a global header should be re-mounted by whichever microfrontend is currently active
- Doesn't recognize overlapping route patterns as a real hazard
- Can't distinguish 'owning a route' from 'contributing a component to someone else's route'
- Assumes route ownership is purely a documentation/convention matter with no technical enforcement
- No mention of shared/always-on chrome as a distinct mounting lifecycle