Learning Book
Home
Page 3 of 1421%

Home

Architecture Patterns Compared

Cross-module catalog: what each pattern is, when to pick it, what to avoid, and a short example. Deep dives live in the linked modules.


1. Track map — where patterns live

What: Patterns are split across modules. Use this page to choose; open the module to implement.

ConcernPrimary patternsModule
UI componentsFeature slices, composition, presentational split1 · Components
App structureHexagonal, Clean/Onion, Layered, Vertical slice, MVC→MVI2 · Application architecture
Domain modelingDDD: ubiquitous language, bounded contexts, aggregates, ACL3 · Domain-Driven Design
Shell & UI kitDesign tokens, app shell, route-driven layout4 · Design systems
Client dataLocal / URL / store / server-cache taxonomy5 · State
Remote dataQuery + thin client, BFF, cache layers, realtime, versioning6 · Data layer
DeliveryCSR / SSR / SSG / ISR / streaming / RSC / Islands7 · Rendering
Org scaleMFE integration, perf budgets8 · MFEs
Ship qualityTesting pyramid, a11y, flags, observability, log contracts9 · Quality
TrustXSS/CSP/CSRF, cookie vs token, privacy10 · Security

Do

  • Start here when choosing; open the module for labs and anti-patterns
  • Prefer the smallest pattern that meets SEO, team, and deploy constraints

Avoid

  • Stacking hexagonal + MFE + event sourcing on day one without a constraint

Example: Greenfield product → Modules 1–6; add Module 7 only when squads need independent deploys.


2. Application structure patterns

What: How the whole app (not just components) is shaped.

PatternCore ideaPrefer whenSkip when
HexagonalDomain center; ports + adaptersNon-trivial rules; multiple UIs; testable coreOne-line CRUD screens
Clean / OnionDependencies point inward through layersSame as hexagonal; long-lived domain3-screen SPA ceremony
LayeredPresentation → app → domain → infraShared infra across many featuresFeatures diverge heavily
Vertical sliceFeature owns UI+use case+adapterSquads ship features independentlyTiny apps with one folder
Modular monolithOne deploy, hard module boundariesDefault for most productsTrue multi-deploy ownership
Strangler figReplace legacy route-by-routeRewrites / migrationsGreenfield

Do

  • Default: vertical slices + modular monolith; add hexagonal ports where rules hurt
  • Use strangler seams + anti-corruption adapters for legacy

Avoid

  • Hexagonal folder trees that still fetch from domain/

Example: placeOrder(cart, orderPort) pure; HttpOrderAdapter at the edge; later extract checkout MFE without rewriting domain.

Detail: Application Architecture Patterns


3. Domain-Driven Design

What: Model software around the business domain — language, bounded contexts, aggregates — not around React folders.

IdeaPrefer whenSkip when
Ubiquitous languageShared terms across UI + API + expertsThrowaway prototypes
Bounded contextsSame word means different things per teamSingle tiny CRUD app
Aggregates + invariantsNon-trivial rules (pricing, eligibility)Forms with no domain rules
Anti-corruption layerLegacy / foreign APIsClean greenfield contracts

Do

  • Keep domain free of React/fetch; enforce critical invariants on the server
  • Translate at context boundaries — no shared god Product type

Avoid

  • Calling feature folders “DDD” without language or contexts

Example: Catalog Product vs Checkout ProductRef; Order.addItem enforces qty ≥ 1.

Detail: Domain-Driven Design


4. Presentation patterns (MVC → MVI)

What: How view and state updates are separated.

PatternIdeaFE fit
MVCController handles inputLoose map to page + handlers
MVPPresenter pushes into passive viewRare in React
MVVMViewModel + bindingsVue/Angular; React via stores/selectors
MVIIntent → model → view stateRedux/RTK, complex React screens

Do

  • Prefer MVI-style unidirectional flow for complex screens
  • Keep views Storybook-friendly without network

Avoid

  • Pattern wars on static marketing pages

Example: Checkout intents (submit) → view-state { status, errors, total } → render.

Detail: Application architecture · §5


5. Component structure patterns

What: How you slice UI ownership and composition.

PatternUse whenSkip when
Feature-sliced foldersMultiple domains ship independentlyTiny app (< ~10 screens)
Presentational / containerData wiring clutters pure UIMost hooks-era screens (colocate)
Compound componentsShared implicit state (Tabs, Dialog)One-off layouts
Atomic DesignDesign-system inventoryAs the only app folder strategy
Inheritance hierarchiesAlmost never in ReactPrefer composition

Do

  • Default to feature folders + composition; promote shared UI after ~3 reuses

Avoid

  • Global components/ dumping ground with cross-feature imports

Example: features/billing/InvoiceList.tsx composes @org/ui Table.

Detail: Module 1 concepts


6. State patterns compared

What: Where data lives determines sync cost and re-render blast radius.

PatternOwnsPrefer for
Local useStateOne component’s UIModals, toggles, drafts
URL (search/path)Shareable view stateFilters, tabs, pagination
ContextLow-churn tree valuesTheme, locale, auth snapshot
Zustand / atomsClient-global UI / feature storeCart, wizard, chrome
TanStack QueryServer cacheAny remote list/detail
Redux ToolkitLarge shared client contractMulti-team legacy / admin
XStateExplicit control flowMulti-step illegal-state flows

Do

  • Classify every field: local → URL → client store → server cache
  • Keep server entities in Query

Avoid

  • Mirroring API entities into Redux/Zustand by default

Example: Shelf — filters in URL, list from Query, isFilterOpen local.

Detail: State concepts


7. Data-layer & CQRS-lite

What: How the client talks to backends; reads vs writes often diverge.

PatternRolePrefer for
TanStack QueryRead model / cacheDefault GET/list/detail
Mutations / use casesCommandsWrites + invalidation
Thin API clientAuth, retries, errorsShared fetch wrapper
OpenAPI / tRPC / GraphQL codegenTyped contractsTeams with a schema
RepositoryDomain verbs over multi-calls2–3 public APIs
BFF / Route HandlerServer aggregationSecrets, joins, shaping
Event-driven busCross-widget / MFE signalsDecoupled producers

Do

  • Treat Query as read side and mutations/use cases as write side (CQRS-lite)
  • BFF when secrets or joins belong on the server

Avoid

  • Caching inside the API client; browser → many microservices

Example: useOrderQuery + usePlaceOrderMutation invalidating ['orders'].

Detail: Data layer · App architecture · CQRS


8. Rendering & delivery patterns

What: Where and when HTML/JS are produced.

StrategyUse whenAvoid when
CSRAuth shells, heavy interactivityPublic SEO pages
SSRPersonalized + indexablePure static (prefer SSG)
SSGStable docs/marketingPer-user data
ISRCatalog/CMS on a scheduleHard realtime
Streaming SSRSlow upstream; early shellNo Suspense boundaries
RSC + client leavesData on server; minimal JS'use client' on whole layouts
PPRStatic shell + dynamic holesToo many holes
IslandsMostly static + few widgetsFully interactive apps

Do

  • Choose per route; push 'use client' / islands down

Avoid

  • One global rendering mode for every surface

Example: SSG docs + search island; streamed cart; CSR admin.

Detail: Rendering concepts


9. Micro-frontend integration patterns

What: How independently shipped UIs compose.

ApproachLoadsBest when
Build-time packagesCompiled into shellFew aligned teams
Runtime federationDynamic remotesIndependent deploy cadence
Server/edge fragmentsHTML before hydrationSEO + fast LCP

Do

  • Thin shell; error boundaries; singleton shared deps

Avoid

  • MFEs before modular boundaries exist; shared Redux across remotes

Example: Server hero + runtime checkout remote + build-time icons.

Detail: MFE concepts


10. Decision cheat-sheet

What: Fast picks when two patterns compete.

If you need…PreferNot
Testable business rulesHexagonal use cases + portsfetch inside components
Shared business languageDDD ubiquitous language + contextsFramework jargon in domain APIs
Same word, different modelsBounded contexts + ACLOne shared god Product type
Squads shipping featuresVertical slicesOne giant services/
Shareable filtersURL stateGlobal store
Remote list/detailTanStack QueryuseEffect + useState
Complex screen flowMVI / XStateFlag soup
SEO + personalizationSSR / streaming / RSCCSR-only
Independent squad deploysRuntime MFEGiant monolith npm bump
Browser authBFF httpOnly session (or memory token)Access token in localStorage
Push updatesSSE/WS → invalidate QuerySecond source of truth in socket memory
Secrets + joins for UIBFFBrowser → many microservices
Legacy rewriteStrangler + ACL adapterBig-bang cutover

Do

  • Write the constraint first, then pick the row
  • Revisit after a milestone — promote patterns when pain is measured

Avoid

  • Adopting every row on day one

Example: 8-person startup → Modules 1–6 patterns. Second squad + separate release train → hexagonal checkout module → later MFE.


Next

  1. Learning path
  2. Application Architecture Patterns — hexagonal & friends
  3. Domain-Driven Design — language, contexts, aggregates
  4. Module 1 · Components