Some microfrontend platforms deliberately use full page reloads (a real HTTP navigation) between top-level sections instead of client-side routing with a shared shell router — e.g. navigating from a marketing site's `/blog/*` to its `/app/*` product experience. When is that the right trade-off instead of building a single client-side-routed shell across all sections?
answer
- coarse zones = full reload, fine-grained = shared shell
- shared runtime = shared fate on bugs/leaks
- marketing site vs logged-in app example
- cost is coordination contract across teams
- hybrid: few reload boundaries + client routing within each
basics
~20 sIf two sections are built with totally different tech, teams, or release cycles, and users rarely bounce between them quickly, it's often simpler and safer to just let the browser do a normal page load between them instead of forcing them into one shared client-side router.
solid answer
~50 sFull-page reloads between top-level sections trade a small UX cost (a visible reload, loss of any client-only in-memory state, slightly slower transition) for real simplification: each section can be built, deployed, and even hosted completely independently — different frameworks, different CDNs, even different domains/subdomains — with zero coordination on a shared route table, shared history-sync contract, or shared runtime dependency versions. This is the right call when the sections are rarely navigated between within one user session (e.g. marketing site vs. logged-in app), when they genuinely need independent tech stacks (a statically-generated marketing site vs. a heavy SPA), or when the cost of maintaining a shared client-side routing contract across many independently-deployed teams outweighs the UX benefit of avoiding a reload for that specific boundary. Coarse boundaries combined with fine-grained client-side routing within each section is a common hybrid.
go deeper
Should recognize that a full page reload is a normal, sometimes intentional choice, not automatically a bug or a sign of a badly built app.
Should name at least one concrete cost of forcing everything into a shared client-side shell (state loss on failure, coordination overhead) versus the reload alternative.
Should articulate the trade-off in both directions with named costs (coordination contract, shared-runtime blast radius) and propose the hybrid coarse-zone model.
Should connect the technical boundary choice to organizational structure and risk tolerance — where a company draws reload-boundary 'zones' often mirrors which teams need to move fast independently versus which experiences genuinely need session continuity, and should weigh this as a standing architectural decision revisited as the org and product evolve.
## When a reload is the right boundary Not every boundary between microfrontends needs to be bridged by client-side routing under one shared shell. A **full page reload** — a real HTTP GET issued by the browser, tearing down the entire JS runtime and starting fresh — is sometimes the correct architectural choice between two sections of a product, and understanding when is as important as knowing how to build the seamless client-side version. ## The case for one shared shell The case for a single client-side-routed shell is preserving in-memory state and avoiding the perceived latency and flash of a full reload — valuable when users move frequently and quickly between sections within one session, e.g. moving from a product listing to a cart to checkout, where losing an in-memory cart state or re-authenticating mid-flow would be a real UX regression, and where the visual continuity of an instant transition matters (no white flash, no re-parsing of a large shared vendor bundle). ## The case against it The case against it — i.e., for accepting a real page reload as the boundary between two microfrontends — rests on a few concrete costs the shared-shell model imposes that aren't always worth paying. 1. **First**, a shared client-side shell requires every participating microfrontend to agree on a common contract: - the same (or compatible) framework runtime version if sharing it via module federation - the same navigation/history-sync conventions - the same route-table format - and the same lifecycle hooks for mount/unmount That's a meaningful, ongoing coordination cost across teams — every participating team's release has to keep honoring that contract. 2. **Second**, sharing one client-side runtime across all sections means all sections share fate on certain failure classes: a memory leak or an infinite loop in one poorly-behaved microfrontend can degrade the whole session for every section, whereas a full reload boundary gives every section a clean slate, naturally recovering from whatever accumulated cruft the previous section left in memory. 3. **Third**, it constrains technology choice — sections joined by client-side routing generally need compatible bundling/runtime approaches (or heavier isolation machinery like iframes or Web Components with shadow DOM to paper over incompatibilities), whereas full-reload boundaries let each section be built with a completely disjoint stack, hosted on entirely different infrastructure, even a different subdomain or domain, deployed on a totally independent cadence. ## The marketing site and the logged-in app A very common real-world instance of this trade-off: - a company's public marketing site (`/`, `/blog/*`, `/pricing`) is frequently a statically-generated site (built with something like Next.js static export, Astro, or a CMS-driven renderer) optimized for SEO and fast first paint, built and owned by a marketing/content team - while the logged-in product application (`/app/*`) is a heavy client-side SPA owned by product engineering with completely different build tooling, release cadence, and runtime requirements Users transition between them relatively rarely and deliberately (clicking 'Sign in' or 'Get started'), so the UX cost of one full reload at that specific boundary is negligible compared to the ongoing engineering cost of forcing both into one shared client-side-routed shell — especially since the marketing site benefits from being simpler, not more SPA-like, and shouldn't have to ship the product app's JS runtime just to exist under the same shell. ## The heuristic, and the hybrid The general heuristic senior engineers apply here: draw the client-side-routed shell boundary around microfrontends that genuinely need to feel like one continuous session to the user and that a team is willing to hold to a shared technical contract; use full-page-reload boundaries (which need almost no cross-team contract at all beyond 'this URL exists and returns valid HTML') for sections that are conceptually or organizationally distant, rarely visited in quick succession, or best served by a completely different tech stack. It's also common, and often the pragmatically right answer, to have a **hybrid**: a handful of coarse-grained, full-reload-separated top-level 'zones' (marketing site, logged-out app, logged-in app, admin console), each of which internally uses fine-grained client-side routing across its own set of microfrontends. This limits the size and membership of any single shared-shell contract to teams that actually benefit from it, rather than forcing an entire company's frontend surface into one router.
- What specific coordination cost does a shared client-side-routed shell impose on every participating team that a full-reload boundary avoids?Every team must keep honoring a shared contract — compatible runtime/framework versions if sharing a module federation host, agreed-upon mount/unmount lifecycle hooks, a common route-table/manifest format, and consistent history-sync behavior. A full-reload boundary needs almost none of that; the only contract is 'this URL serves valid HTML.'
- Why might sharing one client-side runtime across many microfrontends be a reliability risk, not just a coordination cost?If all sections run in the same JS execution context, a memory leak, an infinite loop, or a crashed error boundary in one poorly-behaved microfrontend can degrade or break the experience for every other section in the same session, since they all share the same tab's memory and event loop rather than getting a clean slate.
- In a hybrid model with a few full-reload 'zones' each containing several client-side-routed microfrontends, what determines where a team should draw a zone boundary?Whether users move between the two sides frequently within one session (favoring a shared shell to avoid reload friction) versus rarely and deliberately (favoring a reload boundary), plus whether the two sides can realistically share a technical contract (framework/runtime compatibility) without excessive coordination cost.
It's like choosing between building one seamless building with shared elevators connecting every department, versus separate buildings connected by a short walkway — the walkway (page reload) costs a few seconds but each building can be designed, renovated, and run completely independently.
saying these in an interview costs you the question
- Insists client-side routing across a shared shell is always strictly better
- Can't name any real cost of a shared client-side shell across many teams
- Doesn't consider shared-runtime blast radius as a reliability concern
- Thinks a full page reload is never acceptable in a modern architecture
- No sense of coarse-zone vs fine-grained hybrid structuring