You turn off a feature flag evaluated in the browser. Some users keep seeing the old behaviour for hours. Why, and what should the design do about it?
Show the full answer Hide the answer
The mechanism
A server-side flag takes effect on the next request. A client-side flag takes effect on the next time the client asks - and there are several reasons the client may not ask for a long time.
Four delays stack:
- Session length. A user with the tab open has already evaluated the flag. Unless the client re-evaluates, they hold the old value until they reload, which for a single-page application can be days.
- SDK polling interval. Most client flag SDKs poll on an interval, commonly 30-60 seconds by default, and some only fetch at initialisation. Nothing arrives in between.
- Caching between you and the browser. Flag payloads served through a CDN carry a TTL. A 5-minute TTL adds 5 minutes; a misconfigured one adds hours.
- The bundle itself. If any part of the behaviour was decided at build time rather than read at runtime, turning the flag off changes nothing until the user loads a new bundle.
The consequence people miss
"Off" is not a state of the system; it is a state that propagates. So the flag's real specification is not "on or off" but "on or off, with a worst-case propagation time of T" - and if you do not know T, you cannot use the flag as a safety control.
That matters most for the case flags are sold on: turning something off during an incident. A kill switch with a 30-minute tail is not a kill switch.
What the design should do
- Decide and publish T for your flag system, and measure it. If it is minutes, say minutes.
- Re-evaluate on visibility change and on route change, not only at start-up. A user returning to a tab is the cheapest opportunity to refresh.
- Push rather than poll for the small number of flags that are genuinely safety controls - a server-sent event or websocket channel - and accept polling for the rest.
- Enforce the flag server-side as well for anything that matters. A client flag controls what is shown; a server check controls what is possible, and only the second one is a control.
- Choose the default deliberately. When the flag service is unreachable, the client falls back to a value. That value is the behaviour under failure, and picking it by accident is how a flag outage becomes a feature launch.
When this is the wrong thing to worry about
For presentation-only flags - a colour, a layout variant, a copy change - the tail is harmless and the polling default is fine. The distinction is whether the flag protects anything. If the answer is yes, it belongs on the server, with the client flag as a user-experience nicety rather than the mechanism.