OTA updates vs server-driven UI: push code, or push a description of it?
Server-driven UI moves screens to the backend; OTA updates move code to the device. They solve overlapping problems with very different costs — and most teams that build SDUI needed OTA instead.
Both of these patterns exist to answer the same complaint — "why does changing a mobile screen take a week?" — and they answer it from opposite directions. Server-driven UI (SDUI) moves the definition of the screen to your backend. OTA updates move new code onto the device. The right choice depends on the surface and the operational cost you are willing to own, so it's worth being precise about the trade.
What SDUI actually is
In an SDUI architecture, the app ships a renderer: a set of native/React components plus an engine that takes a server response — usually JSON describing a tree of components — and instantiates the screen at runtime. Change the JSON and the renderer can change the screen without shipping a new binary. That is useful where a defined component set needs frequent content or layout changes.
What SDUI costs
- You're building a UI framework. The renderer, component schema, layout rules, action handling, and analytics wiring need long-term ownership.
- Compatibility is part of the design. Old binaries run old renderers, so server responses need a clear compatibility plan for the renderer versions still in the fleet.
- The expressiveness ceiling. The server can only compose what the renderer supports. A new component type is still a client release. When a schema grows conditions and expressions, treat it as a programming surface and give it the testing and governance it deserves.
- Store policy still applies. Remote configuration is not a policy bypass. Apple's review guidelines prohibit downloaded code that changes an app's features or functionality; assess the behavior you are changing with counsel or the store when it is material.
What OTA gives you instead
An OTA update ships actual JavaScript — real components, real logic, type-checked, code reviewed, testable in CI like everything else you write. No renderer to build, no schema to version; the "framework" is React Native itself. The trade is latency and mechanics: users get changes on their next update cycle rather than next request, and you operate releases — with rollout percentages and rollback paths — rather than flipping server state. For fixing bugs, iterating on features, and evolving product logic, that's not a limitation; it's the appropriate amount of ceremony for changing code on someone's device.
The decision, compressed
- Content-shaped screens that change daily or hourly — merchandising, feeds, campaign pages — and the scale to fund a renderer team: SDUI earns its cost.
- Code-shaped changes — bug fixes, new screens, logic, refactors: OTA is usually the simpler model.
- Just data? If what changes is values, not structure — prices, copy, toggles — you don't need either; remote config or a flag system is simpler than both.
They compose, and that's the mature answer
The pattern we see in well-run apps isn't either/or. It's a small SDUI surface where the business genuinely rearranges content frequently, ordinary React Native code everywhere else, and an OTA channel underneath both — because the renderer is code too. When the renderer itself has a bug, SDUI alone cannot replace it. An update channel can deliver a compatible JavaScript renderer fix; native renderer changes still require a new binary. Start simple; add SDUI when a specific surface proves it needs one.