Skip to content

SYSTEM Cited by 1 source

Zalando Logistics Portal

What it is

The Logistics Portal is a Zalando internal-facing web portal built by the Transport teams inside the Logistics department to serve finance teams, warehouses, and (planned as of 2024-10) third-party partners. It is not the public Fashion Store stack on zalando.com — that runs on the Interface Framework. The Logistics Portal is a separate internal system in a different part of the company, built with a different composition primitive.

Canonical wiki source: sources/2024-10-16-zalando-building-a-modular-portal-with-webpack-module-federation.

Scale at time of writing (Oct 2024)

  • 11 applications hosted.
  • 4 teams currently develop those applications.
  • 5 teams collaborated on the portal project itself.
  • Traffic, QPS, latency, bundle-size figures not disclosed in the public writeup — internal-tooling scale, not customer-scale.

Architecture in one page

         ┌──────────────────────────────────────┐
         │  User browser — Portal host shell    │
         │  (Webpack Module Federation host)    │
         └──────────────────────────────────────┘
                 │                │           │
        (1) /apps│                │ (3) load  │ (4) load
          endpoint│    (2) fetch  │ remote    │ remote
                 ▼     each mfst  ▼  bundle   ▼
         ┌────────────┐    ┌──────────┐ ┌──────────┐
         │ Portal     │    │ app-A    │ │ app-B    │
         │ backend    │    │ manifest │ │ manifest │
         │ proxy      │    └──────────┘ └──────────┘
         │ (auth+     │
         │  authz     │
         │  gatekeep) │
         └────────────┘
          (backend calls forwarded only if authorised)
         microservices (no direct frontend access)

Four load-bearing seams:

  1. Webpack Module Federation host. The portal shell is a Module Federation host; each of the 11 applications is a remote with its own RemoteEntry.js. Host and remotes declare React and React-DOM as singletons, so only one React loads for the whole page.
  2. Centralised backend proxy. Every backend call from any remote goes through the portal's backend proxy, which authenticates the user once and forwards authorised requests to the right microservice. Remotes do not authenticate; microservices do not authorise. Canonical wiki instance of patterns/centralised-backend-proxy-for-micro-frontends.
  3. /applications + per-app manifest.json discovery. On load, the frontend calls the proxy's /applications endpoint; it returns only apps the user can access, each with appId, name, configPath (to a manifest.json), activePath (the route where the app takes over), and an OPA-style opaScope object (per-scope read / write booleans). The frontend fetches each manifest.json (declaring menuItems, requiredPermissions, bundlePath) and lazy-loads the remote's bundle on navigation. Canonical wiki instance of patterns/manifest-driven-micro-frontend-loading.
  4. Prop-based shell API. Every remote receives a single prop from the host, serving as the typed interface for:
  5. user session info (role, permissions),
  6. global app settings (theme / light-dark mode, locale),
  7. portal-wide actions (logout ripples to all remotes; navigation requests; centralised error reporting),
  8. data handoffs between remotes. Canonical wiki instance of patterns/host-shell-prop-api-for-remotes.

Supporting systems

  • Shared UI-kit — internal npm package with reusable components (buttons, modals, input fields, typography) and the Zalando Logistics design language. Published once; updated by dependency bump across all 11 apps. Canonical wiki instance of patterns/shared-ui-kit-as-internal-npm.
  • Webpack shared-dependency configuration — React, React-DOM (and per the post "e.g. React, lodash") marked as shared singletons so a single version loads at runtime.
  • Lazy loading + code splitting — remotes loaded only on activePath navigation; critical-path assets preloaded for likely next interactions.

Why Module Federation (per the authors)

The pre-portal state had two problems the team needed to escape:

  1. Monolithic / static-build approach — every feature change required coordinated multi-team releases, produced bottlenecks, and was difficult to integrate with legacy applications.
  2. iframes — the prior cross-portal integration pattern — were "not scalable" and lacked modern integration primitives (shared React instance, unified auth, cross-frame navigation).

Module Federation delivered:

  • Independent team deploys. Each team's remote has its own CI/CD; the host only needs the URL.
  • Stack autonomy. Each remote picks its own minor versions and patterns, provided the Module Federation shared-dependency contract holds.
  • Legacy continuity. Some applications were still used as iframes inside other portals; Module Federation let them become first-class remotes in the new portal without a forced rewrite of their other deployment.

Contrast with Interface Framework

Dimension Logistics Portal Interface Framework
Audience Internal (finance, warehouses, partners) External (zalando.com Fashion Store customers)
Composition primitive Webpack Module Federation remotes Entity-tree → Renderers
Runtime Browser (+ portal backend proxy) Node.js Rendering Engine + browser runtime
Contribution unit An application bundle A Renderer (one React component per Entity type)
Deploy model Each remote team deploys its own bundle URL Monorepo; Renderers deploy together via the Rendering Engine
Data layer Backend proxy forwarding to microservices Centralised UBFF GraphQL
Auth seam Centralised backend proxy Platform-level
Scale (2024) 11 apps / 4 teams 90 %+ of zalando.com traffic (as of 2021-03), "hundreds of Renderers" by 2023

Both are "micro-frontend" architectures at Zalando; they address different constraints (internal-portal vs customer-traffic) and chose different primitives.

Seen in

Last updated · 501 distilled / 1,218 read