Feature flagging for CakePHP
I wanted to share a new CakePHP plugin that provides feature flagging. In a Saas environment, I’ve been a long time advocate for using feature flags to release changes instead of deploys. Feature flags let you better manage release risk by allowing you deliver code with new features disabled. Once your change has been deployed, you can gradually introduce user traffic by enabling the related feature flag, and validate that your new feature is well behaved and performs well before enabling it for all users.
Feature flags let you deliver software rapidly with lower risk and quicker time to recovery when something goes poorly. As a long time user of feature flags, I have some opinions on how a good feature flagging system should work and I wanted to bring that to CakePHP.
Feature flag plugin
I’ve put what I think makes good feature flagging into a plugin. First install and enable the plugin:
- composer require markstory/cakephp-feature-flags
- bin/cake plugin load FeatureFlags
Next is a decision on how much complexity and granularity you want from your feature flags.
- Simple Feature flags are booleans that can be on/off and have no additional logic behind them. Simple feature flags give you simple switches that are enabled for all users.
- Rules based Feature flags are driven by boolean logic that is expressed in configuration files. It gives a high-degree of control and can perform precise targeted rollouts to individual users.
If you’re new to feature flags, I would recommend starting with Simple Feature Flags. You an always switch the backend out once you get comfortable with feature flags. To get started with feature flags, first create a configuration file config/features.php
, with the following:
- <?php
- return [
- 'Features' => [
- 'calendar-v2' => true,
- 'checkout-v2' => false,
- ],
- ];
In your Application::services()
method add the following:
- use FeatureFlags\FeatureManagerInterface;
- use FeatureFlags\Simple\FeatureManager;
- public function services(ContainerInterface $container): void
- {
- // other services
- $container->addShared(FeatureManagerInterface::class, function () {
- return new FeatureManager(Configure::read('Features'));
- });
- }
With the DI container setup, you can have CakePHP inject the FeatureManager into your controllers, and commands as required.
- public function view(FeatureManagerInterface $features, $id)
- {
- if ($features->has('calendar-v2')) {
- // Logic for the new feature.
- return $this->render();
- }
- ...
- }
Deploying feature flags
In the example above feature flags are read from configuration files. I try to keep my systems as simple as possible, and reading from a configuration files is generally simpler than reading from databases and caches. However, you choose to store your feature flags, it is important that you can make changes to them quickly.
In the systems I build, I usually invest in the ability to deploy configuration quickly and separate of the application. In smaller applications this can be an ansible playbook that replaces configuration files that the application is symlinked to. In more complex applications this could be a `ConfigMap` mounted into kubernetes pods.
I hope this plugin helps folks deploy changes with greater safety and confidence and I’m interested in hearing from the CakePHP community on where this plugin should go next.
There are no comments, be the first!