Feature flags service

6 Oct 2021

Hello everyone! Today I would like to share my experience of creating a simple service for managing feature flags. Feature flags allow you to enable or disable some specific functionality in an application. It does not require re-deploy or rollback. Only need to enable or disable a specific feature flag. Besides that, flag checks should be added at some points in the source code.

For example, we need to add a contact form to the website, but it's also important to quickly revert changes if needed. Then we would create contact-form feature flag and check it when displaying the form and in the form handler.

Existing services

There are a lot of existing services, that implement the feature flags concept. There are several examples:

There are free and paid, proprietary and opensource, SaaS, and self-hosted. Besides feature flags management they also can implement additional options like A/B testing.

Own self-hosted service

I implemented my own self-hosted service feature flags management service for use in personal projects. There are several advantages of such an approach:

  • It's free, there are no limitations. There can be an unlimited number of flags and projects.
  • It's customizable. It's possible to implement custom logic if needed.
  • It's simple, this service doing only one job.
  • There is no external service dependency.
  • This service can be used locally without the internet, or in a private corporate network.

There are also some disadvantages: you would maintain it by yourself, and there is only basic functionality.

Structure

The main entities are Project, Environment, and Feature.

There is such database structure:

The project represents a real project, that uses a feature flags service. For example, for this website, it would be antonshell_me. There can be an unlimited number of projects, each project has its own access keys, environments, and features.

Environment represents context, like prod, dev, staging.

Feature represents some functional. For example, post_comments, contact_form etc. The feature can be enabled or disabled for a specific environment. For example, new functionality should be tested on staging, and only after that enabled on production.

Access levels

There are several access levels:

  • Root - allows managing projects. View, create, update and delete.
  • Manage - allows managing specific projects. Allows creating environments and features, enabling/disabling features.
  • Read - allows reading features values.

Client

Client code can interact service with Curl, Guzzle, or any other HTTP client. There is also implementation for Symfony application with unit test.

Usage examples, documentation

Service is available on github and can be launched locally or on a private server. Installation is described in README.

There is also the demo available. The demo project can be used for testing purposes:

{
  "name": "demo",
  "owner": "antonshell",
  "read_key": "demo_read_key",
  "manage_key": "demo_manage_key"
}

Service can be used with API. API structure is described with Swagger.

There is such a request for creating a project. Root token is configured with ROOT_TOKEN env variable. When a project is created, there are also created prod, stage, dev environments, and demo-feature.

curl --request POST \
  --url https://feature-flags.antonshell.me/manage/project \
  --header 'Authorization: bearer root_token' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "project1",
    "description": "project1",
    "owner": "antonshell"
}'

Create additional environment:

curl --request POST \
  --url https://feature-flags.antonshell.me/api/environment \
  --header 'Authorization: bearer demo_manage_key' \
  --header 'Project: antonshell/demo' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "qa1",
    "description": "QA1"
}'

Create feature:

curl --request POST \
  --url https://feature-flags.antonshell.me/api/feature \
  --header 'Authorization: bearer demo_manage_key' \
  --header 'Project: antonshell/demo' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "feature4",
    "description": "Feature 4"
}'

Enable/disable feature for specific environment:

curl --request POST \
  --url https://feature-flags.antonshell.me/api/feature/feature4/value \
  --header 'Authorization: bearer demo_manage_key' \
  --header 'Project: antonshell/demo' \
  --header 'Content-Type: application/json' \
  --data '{
    "enabled": false,
    "environment": "prod"
}'

Get feature value for specific environment:

curl --request GET \
  --url https://feature-flags.antonshell.me/feature/antonshell/demo/feature1/prod \
  --header 'Authorization: bearer demo_read_key'

Conclusion

Finally, we have simple self-hosted feature flags management service. It supports features separated by projects and environments.

Source code is available github. Demo is also available. If you would like to use demo with custom project, please contact me in Telegram.

That's all for today. Thank you for your attention!