The Promise of Server-Driven UI
Server-Driven UI (SDUI) is often sold as a silver bullet: faster iteration, remote configuration, and the ability to change UI without shipping a new app version.
All of that is true.
It is also why so many SDUI systems fail.
Most failures do not come from performance issues or missing features. They come from a fundamental misunderstanding of what SDUI actually is. The hard part is not rendering JSON. The hard part is designing stable UI contracts that can evolve over time.
If you get the contract wrong, SDUI quickly turns into an untyped, untestable, and brittle system.
Why Naïve SDUI Breaks Down
The most common SDUI implementations start with a dangerous assumption:
“If we can describe the UI in JSON, we can render anything.”
This usually leads to systems that resemble HTML-over-the-wire, except without the decades of tooling and standards that HTML benefits from.
Common Failure Modes
Naïve SDUI systems tend to:
- Treat SDUI as serialized markup
- Encode layout, style, and behavior in the same structure
- Skip schema validation in favor of “flexibility”
- Let backend responses directly shape UI structure
At first, this feels powerful. Over time, it becomes impossible to reason about, change safely, or refactor.
Flexibility without constraints is not power-it is technical debt.
SDUI Is a Contract, Not a Renderer
The key mental shift is simple but non-negotiable:
SDUI is a contract between server and client.
The renderer is the easy part. The contract defines:
- What the server is allowed to ask for
- What the client guarantees it can render
- What happens when either side evolves
Once you frame SDUI as a contract, most design decisions become clearer.
Think in Primitives, Not Screens
The fastest way to break SDUI is to model “screens” or “pages”.
Screens are:
- Too specific
- Too coupled to product concepts
- Too fragile to evolve
Instead, SDUI should be built on primitives.
Typical primitives include:
- Text
- Image
- Card
- List
- Section
- Action
These primitives form a shared vocabulary. Meaning emerges from composition, not from specialized components.
If a primitive needs to change, you update it in one place. If a screen changes, you recombine primitives instead of inventing new ones.
Schema First, UI Second
A good SDUI system is schema-driven.
Schemas should answer very explicit questions:
- What can be rendered?
- What cannot be rendered?
- Which fields are optional?
- Which fields are mandatory?
- What defaults exist?
Type safety is not an enhancement in SDUI. It is survival.
Without schemas:
- Validation moves to runtime
- Errors surface in production
- Refactors become dangerous
With schemas:
- Contracts are explicit
- Changes are intentional
- Evolution is controlled
The schema is the product of SDUI, not the JSON payload.
Where SDUI Actually Shines
SDUI is not a universal solution. It excels in specific areas:
- Recommendation and feed-based sections
- Feature flags and experiments
- Content-heavy surfaces
- Cross-platform UI parity
These are places where structure is stable but composition changes frequently. SDUI allows iteration without redeploying clients while keeping rendering predictable.
Trying to drive every pixel of your app through SDUI is usually a mistake.
Designing for Evolution
The best SDUI systems assume change.
- New primitives will be added
- Old ones will be deprecated
- Fields will evolve
- Clients will lag behind servers
A good contract supports this gracefully.
Backward compatibility, defaults, and validation are not afterthoughts-they are core design requirements.
Key Takeaways
- SDUI is a contract, not a renderer
- Primitives scale better than screens
- Validation beats flexibility
- Evolution matters more than perfection
