Setting up GitLab feature flags without the unleash client library

Last friday I finally learned how to use GitLab feature flags (wrapper around unleash). I know they've been around for ages, but last time I checked the documentation I found that they recommed using a clientside library for working with the unleash api, and the one for python doesn't support asyncio 1, which is a dealbreaker for me.

But last week I gave it another look and found out that it's actually much simpler than I had assumed, and that using the client library is a total overkill (as long as you're using the basic features of unleash).

Here's how to get started in five steps:

  1. Go to your gitlab project > "Deploy" > "Feature flags"
  2. Click "Configure"
  3. Copy the api-url and the instance id (instance-id)
  4. On the same gitalb page, create a feature flag through "New feature flag"
  5. In you app, send a request to GET {api-url}/features with the headers unleash-instanceid: {instance-id} and unleash-appname: {environment} and that's it!

The environment is a value you choose. Gitlab docs suggest using the same value as your CI deploy script but it's not necessary. You can use the environments to make certain flags available to only certain instances of your application.

One thing that cought me up a bit is that you have to send a unleash-appname even if your feature flag is scoped to all environments.

The api returns a payload like this:

{
    "version": 1,
    "features": [
        {
            "name": "<you_feature_name>",
            "description": "<Your feature description>",
            "enabled": true,
            "strategies": [{"name": "default", "parameters": {}}],
        }
    ],
}

With this you can use any http client you want.

Before diving into it, I'd suggest taking a couple of extra steps to make sure you're not creating a hard dependency on gitlab from your application:

  • Client-side caching - store a copy of the flag statuses in your application.You'll only need to check back with the gitlab api every few minutes, so you save them some network traffic, or at least you'll have some value to fall back on in case gitlab goes down for a short time.
  • Always have an explicit default value for the flag which makes the most sense for the feature behind it.Make sure your app works well when all flags are at their default values.Don't just default to all-features-enabled or all-features-disabled, have a think about it on feature-by-feature basis.
  • Robust error handling - having a fallback and default values is part of it, but it bears reiterating; you're calling out to an external service and that's not a small deal, especially on a critical code path.Make sure it's wrapped with error handlers and timeouts, so that loosing the dependency doesn't kill your application.
  1. As of this writing there is an open issue for it on github.