Feature flags vs SDUI vs remote config
Feature flags toggle code you already shipped. Remote config swaps copy and numbers. SDUI rearranges native widgets from JSON. They stack; they are not the same.
Feature flags toggle code you already shipped. Remote config swaps copy and numbers. SDUI rearranges native widgets from JSON. They stack. They are not the same product, and treating them as rivals is how paywall tests get messy.
Flow-UI does not ship a flag service. Your host flags plus Flow-UI pages is the stack. RevenueCat-style remote paywalls, Featureflow-style flags, and "flags vs SDUI" blog posts are the industry conversation this article answers without inventing a Flow-UI flag SDK.
Feature flags#
A flag is a boolean (or a multivariate key) consulted in code you compiled.
You already shipped both views (or you shipped a no-op). The server cannot invent NewCheckoutView. It can only choose. Kill switches, gradual rollouts, and "this API is dangerous in this country" belong here.
Flags are the wrong tool for "put the banner above the title this week". That is a tree edit, and you will end up with a combinatorial explosion of flags that each wrap a VStack order.
Remote config#
Remote config is a bag of values: strings, numbers, JSON blobs that are not a page envelope. Copy, timeouts, image URLs, minimum versions.
It is excellent for "change the headline on the hardcoded hero". It is a poor page composer. The moment the blob contains sections and widgets, you have unofficial SDUI with no registry, no lossy decode, and no diagnostics.
Keep remote config for scalars. When the value is a page, use a page document.
SDUI#
SDUI's unit is the page. The backend composes widgets that exist in the binary. Experiments can be a different document for cohort B. You do not compile two homes. You compile widgets.
Actions still fire as data. A flag is not an ActionData. A page mutation is not a flag flip.
Paywalls and A/B tests#
A paywall A/B test can be:
- Two handwritten SwiftUI views behind a flag (fine when the paywall rarely changes)
- Remote config copy on one view (fine for headlines)
- An SDUI page of widgets (fine when growth edits layout weekly)
What you must not do is hide a paid feature from App Review by downloading its UI after approval if the feature is not in the binary. That is not an SDUI tutorial. That is a guideline problem. Read Apple. This article will not tell you how to hide features.
Decision table#
| Need | Tool |
|---|---|
| Kill switch for a code path | Feature flag |
| Change a number or a string on a hardcoded view | Remote config |
| Reorder native widgets, add a known type | SDUI page |
| Brand new gesture / widget type | App Store binary, then SDUI can place it |
| Web checkout you do not own | WebView destination, not a flag |
Migration pattern that actually works#
Week 1: SDUI off. Flag default false. Envelope exists in staging.
Week 2: Internal builds on. Production still handwritten.
Week 3: 5% of production sessions, with DecodeDiagnostics in logs.
Week 4: Raise the percentage. Keep the handwritten home until the envelope is boring for a month.
Do not delete the old home on the day you merge the package. Flags exist for that.
Implementation notes for Flow-UI hosts#
Gate FlowPageView behind a flag if you are migrating. Keep the handwritten home until the envelope is boring.
Do not parse feature flags out of widget data unless you enjoy two experiment systems. Let the backend emit the page the cohort should see.
PageLoader can attach cohort headers. That is host policy. The package does not know what a cohort is.
Questions this article should close#
Can a flag replace a page document?#
Only if both trees are compiled. The flag chooses a view you shipped. It cannot compose widgets you did not register.
Can remote config hold a full envelope?#
It can, poorly. You will miss lossy decode, diagnostics, and a registry. When the blob is a page, put it on a page route.
Read next#
Flags toggle code. Config swaps values. SDUI composes widgets. Use all three; do not make one of them pretend to be the others.
Related documentation
Related articles
- Architecture4 min read
When not to use server driven UI
Skip SDUI for maps, heavy gestures, latency-critical canvases, and apps that change UI once a quarter. Use it for feeds, merchandising, onboarding, and experiments.
- SwiftUI3 min read
What native means in an SDUI stack
Native SDUI means the widget is a real SwiftUI view: scrolling, gestures, and accessibility come from the platform, not from HTML.
- Server-Driven UI4 min read
How to implement SDUI on iOS
Implement SDUI on iOS by decoding a page envelope, registering widgets, containing unknown types, and dispatching actions as data.
More on the blog.
Read the source
Flow-UI is MIT licensed. The schema, renderer and starter widgets live on GitHub.
GitHubGet started with Flow-UI
Install the Swift package, register a widget, and render a page from JSON.
Get started