Web application state is tricky. We want a fast reactive UI, a simple
state (preferably in one place), and most importantly, we want the UI to
reflect that state correctly.
Customers like snappy apps, but state management is where the bulk of
hard problems lie. If the UI is wrong, the user is going to be immensely
The web application trilemma is our
attempt to visualize some of the trade-offs in current web frameworks
and the patterns they apply.
The trilemma states that we can never fully reach both a fast and
correct UI, in conjunction with a simple centralized state in a web
The gist is this;
- To get a Fast UI, sacrifice state simplicity or UI
correctness (introduce bugs).
- To achieve a Correct UI, give up state simplicity
(distribute it) or speed.
- To reach a Simple State, compromise on either the UI
correctness, or speed.
Let’s examine the trade-offs closer.
Say we drop the requirement for a fast and reactive UI. That leaves
us with Simple State and a Correct UI. The state
should live in a single location (the back-end) and the app should
visualize that state alone. We get the proven stateless architecture:
Request-response like the web was originally meant to be. Server-side
frameworks shine on this edge of the triad.
Laxing the requirement of a simple state gives us opportunity to
speed up the UI. By transitioning to the Correct and Fast
UI edge we introduce loading states, hydration and optimistic UI.
Here the user-perceived latency is minimal.
But as we distort the perception, so too do we distort the state of the
app: Optimistic UI updates require a client-side state in addition to
the slow server-driven state. This leads to a distributed state, divided
between the client and the server. To keep the UI correct, we have to
carefully coreograph the responsibilities of each. The back-end is no
longer the single source of truth.
front-end plus an API layer. Everyone tries
to avoid mutable state on the server. According to the trilemma, a
simple centralized state is difficult to throw in to the mix.
The edge where nobody wants to be (but and most tutorials seem to be
going) is Simple State with a Fast UI. Here, the
front-end is firing multiple requests in a network waterfall and the UI
is struck by spinnageddon.
The state is distributed and duplicated in a myriad of requests, each
But when regarded as a whole,
it yields a composition with many incorrect states.
Error handling and edge-cases, such as race conditions, are overlooked.
The UI is fast, but fragile as a crystal ball, and about as useful as
Is the trilemma true?
Well, there are frameworks which try to work out a mix of all three.
These technologies sit somewhere in the middle of the triangle. So far,
none have achieved trinity.
We’ve noticed two distinct approaches emerge. Some frameworks rely on
architecture. They aim to partially replace the browser’s
request-response networking with RPC
Others emphasize server-side rendered static HTML
with a minimal amount of JS. These frameworks are alignined with the
original hypermedia conventions and rely more on browser
If anything, these are a glimmer of hope to break the web app