Articles · App ExamplesUpdated September 2026

Add feature flags to an app and a bad release becomes a switch you flip, not a build you submit.

A feature flag is a value your app fetches from a URL you control and checks before it renders something. Adding one is a small JSON file, a fetch on launch, a cached copy for when the fetch fails, a default compiled into the app, and an if statement. The limit worth knowing before you start: a flag only moves code that is already inside the binary people installed. It cannot deliver a feature you have not submitted, and Apple's guidelines say not to ship hidden or dormant features anyway. A flag is also not a replacement for testing before launch. It shortens how long a mistake stays live, which is a different job.

This page covers why the release clock makes a remote switch worth having on a phone, and what the switch is worth when something breaks. Then the three places the value can live, and what a staged rollout in the store will not do for you.

See how long a mistake stays live

The short version

A flag is one if statement and one decision about who flips it.

Two things arrive when you add a flag. The code gains a branch, which is a few lines. The product gains a control surface, which is a support question, a person who owns the switch, and a second state your testing has to cover. The first is nearly free. The second is why flag counts creep and nobody ever deletes one.

So reach for a flag when being wrong is expensive and the fix would otherwise be a store submission. Skip it when the change is small, reversible in the next release, and nobody is going to be woken up about it.

Why the release clock changes the maths on mobile

On the web you fix a bad deploy by deploying again. On a phone two queues sit between you and the fix. The store has to review the build, and then every user has to install it. Apple is public about the first one: on average, 90 percent of submissions are reviewed in less than 24 hours, and you can request an expedited review when you are fixing a critical bug in a live app.

So review is usually a day, not the week of folklore. A day is still the wrong day. It starts after you notice, after you write the fix, after the build finishes, and it ends at a version most of your users do not have yet. Automatic updates are not instant and not universal.

That second queue is the part people forget, and it is the real argument for flags now. A user on the old binary stays on the old binary until their phone updates it, and no amount of expediting moves them. A flag skips both queues, because the code is already on the device and you are only changing the value it reads.

Apple, App Review: review status and expedited reviews

What the switch is actually worth

Measure a flag in exposure: how many people met the broken thing, and for how long. You control both halves. The percentage you enable decides how many, and the speed of the switch decides how long. A staged rollout at 5 percent with a slow switch and a full launch with a fast one can produce the same damage.

Speed depends entirely on when the app reads the value. Read it once at launch and a user who leaves the app in memory for three days keeps the old answer for three days. Read it again on every foreground and your worst case is one session. Push the change and the worst case is seconds, at the cost of a socket and a lot more that can go wrong.

You also have to see the result, or the switch is a light in a dark room. Put the flag value on the events you already send, so that crash rate for people with the new checkout is one filter rather than a research project. That overlap with mobile app analytics is what turns a rollout into a measurement instead of a hope, and it is what tells you when to go from 5 percent to 50.

Try it

How long the mistake stays live

Roughly how many app openings meet a broken feature, if you can switch it off against if you have to submit a fix.

1,083 openings, not 5,000

A flag ends it about 6.5 hours after the feature goes wrong. A fix you submit ends it about 30 hours later at best, using Apple's own figure of under 24 hours for 90 percent of submissions, and then only for people who install the update. Difference: 3,917 openings. At 100 percent you are rolling back, not rolling out. Start lower and the first number drops with it.

Three places the value can live

The cheapest version is a JSON file on any storage you can put behind a CDN. The app fetches it, keeps the last good copy on disk, and falls back to a default compiled into the binary when there is no network. You edit the file and the next fetch picks it up. No SDK, no account, no vendor. For an app with two or three switches this is the right answer, and people talk themselves out of it because it looks too simple to be serious.

The middle option is a hosted remote config service. You get a console, typed values, audience rules, and a client that handles caching for you. The cost is another SDK in the launch path and someone else's cache rules to learn. Check the refresh behaviour before you trust it: config clients commonly cache for hours by default, which quietly turns your kill switch into an afternoon.

The top option is a flag platform, with per-user targeting, audit logs, scheduled changes and experiments attached. That is worth paying for when flags are how your team ships, not when you have three of them. We have not verified current pricing for any specific vendor, so check it at the source rather than trusting a number in a blog post, this one included.

Whatever you pick, keep the fetch off the critical path. A blocking network call before the first screen turns every flag into a launch time regression. Launch time is the number users actually feel, which is why it sits in the middle of any honest conversation about app performance. Render from the cached value, fetch in the background, and apply the new value at the next safe moment.

The stores have their own dials, and they are not flags

Google Play can release an update to a percentage of users through a staged rollout, and App Store Connect has a phased release that drips a version update to automatic updaters over 7 days. Both dials decide who gets a new build. Neither can change what a build does once it is installed, and anyone can still download the newest version by hand on day one. That is the whole difference between a release strategy and a feature flag.

Managed publishing on Play is the closest a store gets to a switch. The update goes through review as normal, and after it is approved you choose exactly when it goes live. Useful for a launch date. Still a release, so it is no help at two in the morning.

Do not plan around a fast review either. Google says certain apps are subject to extended reviews, which may result in review times of up to 7 days or longer in exceptional cases, and says some developer accounts get the same closer look. Any plan whose rollback step is submit a fix has a seven day tail hidden in it.

And the flag still cannot do the two things people want from it. It cannot run code that is not in the binary, so a native module, a new permission or a changed app icon is a fresh submission every time. It cannot shrink your test matrix either, because each independent flag doubles the states the app can be in, and five of them is thirty two combinations you are shipping at once. Which changes you can make while shipping without a new build, and which force a resubmission, is the store side of the question and a walkthrough of its own.

Google Play Console Help, publishing status and review times

Where the switch can live and what each one gives you

Where the value livesTime to set upChanges a shipped appPercentage rolloutTargets named users
A constant in the codeminutesNoNoNo
A JSON file you hostan afternoonYesif you write the bucketingNo
A hosted remote config servicea dayYesYesby audience rule
A flag platform with an SDKa day, plus a billYesYesYes
The store's own staged rollouta console settingNoYesNo

Building the switch into an app you own

None of this is hard to build. It is a fetch, a cache, a default and a branch, plus the discipline to delete the branch two releases later. What makes it feel hard is that it touches launch code, which is the part of an app people are most nervous about editing, so write the failure path first and the happy path second.

Newly is an AI app builder. You describe the app and it writes a real React Native and Expo project you own. It runs the app on a cloud iPhone or Android simulator while it builds, then ships to TestFlight and to Google Play internal testing. It is $25 a month and there is no free plan. The documentation does not describe a flag console, so treat the switch as something you add yourself. Ask the agent for the fetch, the cache and the compiled default. Or take the code out as a ZIP from Settings, or through the two-way GitHub sync in the Deploy tab, and wire it up by hand.

Decide one thing before you write any of it. What does the app do when the fetch fails on a cold start with no network? The answer is the compiled default, and the compiled default should be the safe state, which almost always means off.

Questions people ask about feature flags

A value the app reads at runtime and checks before it shows something. It lives outside the binary, usually in a small JSON file or a config service, so you can change what an installed app does without shipping a new one. The code for the feature is already on the device. The flag only decides whether it runs.

Describe the switch before you need it

Write down which feature gets a flag, what the app does when the fetch fails, and who is allowed to flip it, then build the fetch, the cached default and the branch into the launch path.

Start building