Frontend Architecture and the Illusion of Boundaries
Introduction
Recently I reviewed a proposal in our Angular codebase introducing domain-based folders and facades between domains.
On the surface, it makes sense:
split code into domains
avoid cross-domain imports
expose public APIs
use facades for communication
But it raised a deeper question:
Are we actually reducing complexity, or just adding structure to manage complexity created by our architecture?
Frontend vs Backend: Different Nature of Problems
Backend systems naturally fit Domain-Driven Design because they deal with:
business consistency
transactional boundaries
long-lived domain rules
data ownership
Frontend systems are fundamentally different. They are:
user-flow driven
interaction-driven
UI composition driven
rapidly changing with UX
A single user journey often spans multiple backend domains:
account
payments
address
notifications
But to the user, it is still one flow.
This difference matters more than we usually admit.
A Concrete Example: Cross-Domain Flow in Angular
Take a simple flow:
A user applies for a new card and updates their mailing address during the process.
In a domain-split Angular architecture, this is typically divided into:
Card domain
Customer domain
Now Card needs to trigger an update in Customer.
Because direct access is discouraged, we introduce:
a Customer facade
an interface contract
an implementation hidden behind store/effects/services
So the flow becomes:
1 | Card Domain |
A simple user intent becomes a multi-layered coordination chain.
Why This Feels Strange in React
To React developers, this often feels unnecessary.
Not because cross-feature dependencies don’t exist — they absolutely do — but because React tends to handle them differently.
Instead of introducing:
domain facades
interface contracts
global orchestration layers
React relies more on:
component composition
local state ownership
direct capability usage through hooks
Dependencies are handled through composition, not architectural indirection.
The Real Question
This leads to a more important question:
If the dependency already exists in the user flow, what do we actually gain by wrapping it in facades and domain boundaries?
We are not removing coupling.
We are:
formalizing it
layering it
redistributing it across abstractions
So the real question becomes:
If coupling is unavoidable in frontend flows, should we organize the system around domains at all — or around user flows instead?
The Microservice Parallel
This feels very similar to microservices.
Many systems moved from monoliths to microservices believing:
the monolith is the problem
But often the real issue was:
poor modularization
unclear boundaries
tight coupling
So complexity was not reduced — it was moved across boundaries.
Frontend architecture can fall into the same pattern:
domains
facades
interfaces
orchestration layers
We may end up managing complexity instead of reducing it.
Conclusion: Boundaries Should Follow Workflows
I still believe modularization matters.
But frontend systems are not primarily domain systems — they are workflow systems.
They optimize for:
interaction, not consistency
composition, not strict boundaries
user flows, not domain purity
In many cases, workflow or feature-level boundaries are more natural than backend-style domain boundaries.
Good frontend architecture should reduce coordination cost and improve composability — not introduce layers that only exist to manage existing layers.

