Your app needs server-supplied feature flags to toggle new capabilities

Suppose you want to introduce a new feature to your app, and this feature is somehow dependent on the server. Let’s call this feature ZOINK.

You need to follow a sequence of steps that allow your new feature to be supported. It goes something like this:

Implement ZOINK in the server, and deploy a new version of the server Deploy a new version of the client app that supports ZOINK

That’s simple enough. However, suppose you’re not sure whether ZOINK will be a good feature; you may want to do a slower rollout, or perform some A/B testing for a while. While you can usually do that with app releases, it means your build version is now linked to whether you want someone to get ZOINK on their app or not. Releasing normal bug fixes while doing a staggered app rollout is more complicated.

To complicate matters more, suppose the version of the server supporting ZOINK requires a different payload of some kind, making it actually incompatible with older versions of your app. You might need a more complicated set of steps — including intermediary versions of the app and the server, and potential app forced updates — to get your feature out to the public without leading to crashes or version mismatches. Or suppose you want to disable ZOINK right after rollout; you now need to do it all again, going through the motion of doing new releases for both the client and the server.

The gist of it is, it gets complicated.

The solution to this is something called feature flags. This has been discussed at length before by other people (including by Martin Fowler and Justin Baker), so I won’t have to get into detail, but it basically means that the server should tell the client what features it supports.

This is done by either a simple JSON payload, or a request of some other kind during app initialization. Many services already offer this as a feature, including Unity Analytics’ Remote Settings and Firebase’s Remote Config, for example.

When this is implemented, what your app does is check this list of supported features, and then perform business logic accordingly. It does mean that your app will ship with dual implementations for some piece of functionality, but more importantly, it means you can toggle this feature on and off at will. This is great even if you only have one target server/environment running at a time. The value for that flag can also be based on a user dimension; for example, if you only want 10% of your users to have that feature enabled, you can check against some unique client id and return a weighted result. More importantly, overall, it means a lot less coordination between server and client releases, and assures breaking feature releases are painless.

Of course, feature flags can also be used for other parameters, such as toggling API server rates, minimum/maximum values for some range, or controlling any other piece of business logic, all in near real time and with no app updates required.

It might sound like a fancy feature, but I’ve seen breaking server changes between different releases, and believe me, it’s not pretty. It’s only now that I realize a lot of problems I’ve had in the past would have been easily avoided with feature flags. Apps can great benefit from feature flags; ignore them at your own peril.