Skip to content

Instantly share code, notes, and snippets.

@nwillems
Last active February 22, 2021 19:37
Show Gist options
  • Save nwillems/a65126c0065950937eb4c65d1a0345fa to your computer and use it in GitHub Desktop.
Save nwillems/a65126c0065950937eb4c65d1a0345fa to your computer and use it in GitHub Desktop.
CTFF - Capture The Feature Flag

Capture The Feature Flag

To provide feature flags you need 3 things, the target, the flag and the context.

thing what it is?
target the identity of the application/service/endpoint/flow
flag the actual toggle
context the current context of "execution"

The reason for needing the target, is to allow the system to work in an infrastructure setting, rather than serving a single service, in which case the system might as well have beem directly integrated.

The target further allows a single application to have multiple paths, eg for A/B testing.

The flag is the actual flag being toggled

The context, is a scoping mechanism, that the client should provide, eg a customer ID, or a authorization group or ...

Feature flag service - architecture

The service is divided into two components, the flagger and the changer. The flagger service is responsible for providing the backend for any of the business services that need feature flags. The changer, is responsible for the audit logging in relation to toggling of feature flags.

In the following the basic API of the two services will be described.

Flagger endpoints

The flagger service utilizes a service authentication mechanism - called Auth-identity.

POST /:identity/register
Authentication: Auth-Identity

flag_0
flag_1
...
flag_n

The register endpoint should be called by an application on startup. The intent is to collect the set of currently available flags

GET /:identity/state/:flag_name?ctx=:context_id
Authentication: Auth-Identity

The state endpoint will tell an application wether a given feature flag is on or off.

Changer endpoints

The changer service uses an external(corporate/sso) authentication mechanism, to authenticate human users.

GET /:identity/flags
Authentication: sso-identity/corp/...

The flags endpoints returns a list of flags and their respective state.

POST /:identity/flags/:flag_name
Authentication: sso-identity/corp/...

on|off|true|false|context-id(s)

The state endpoint sets the state of a given flag, the most prominent functionality of this endpoint, besides setting the flag, is audit logging, binding the sso-auth together with the updated state.

Implementation

It is envisioned that the service can be implemented rather simply, by leveraging native kubernetes object. A mapping from the api concepts presented above, to kubernetes artifacts has been provided below.

:identity - is a configmap

:flag_name - a key in the identity-configmap

auth-identity - a service-account token, which has access to read the specified configmap

An implementation like this, also allows for a progressive roll-out, or roll-in(is that a thing?), where certain workloads will read their feature flags from files mounted from the configmap, while still allowing the changer service to update the feature flags.

Further, by leveraging service-accounts, most of the logic around auditing is already taken care of.

The changer service will still need a third-party authentication mechanism, this is envisioned to be by oauth/oidc or similar mechanism.

The user-facing frontend could either be a small SPA or implemented as a CLI-tool - the advantage of the cli-tool being easy integration into cicd pipelines.

@feature.flag("feature_flag")
def my_conditional_function(real_arg, real_arg2, feature_flag):
if feature_flag:
# do the new hot thing
else:
# do the old and known good thing
# in the above code, the decorator records the feature flag and upon application startup, reports all collected flags to the
# feature flagging service
# at runtime the decorator requests and caches the feature-flag value, and injects it into the function.
# I believe a similar mechanism can be implemented for both java, and c#
@nwillems
Copy link
Author

the context is sort of a fluffy concept, but it felt important to include a mechanism to allow request overriding or gradual roll-out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment