DEV Community

Cover image for Feature flags in your Symfony project 🌱
Marc Guinea
Marc Guinea

Posted on

Feature flags in your Symfony project 🌱

Feature flag, or also known as Feature switch, is a functionality that allows to your app to enable or disable some parts on runtime depending on your needs.

Why?

There are many reasons to implement feature flags in your project:

  1. An specific feature must be available for a single customer at first.
  2. You have to deploy it but it's not finished yet.
  3. Feature is production ready but there is an specific date to be available to public API...

How?

First of all, let's create an interface to abstract the implementation:

interface FeatureChecker
{
    public function isEnabled(string $feature): bool;
}
Enter fullscreen mode Exit fullscreen mode

At this point, we can implement it in several ways. Let's see the easiest one: In Memory implementation

class InMemoryFeatureChecker implements FeatureChecker
{
    private array $features;

    public function __construct(array $features = [])
    {
        $this->features = $features;
    }

    public function isEnabled(string $feature): bool
    {
        return $this->features[$feature] ?? false;
    }
}
Enter fullscreen mode Exit fullscreen mode

If using Symfony, we can use Service Container to set that feature flags in a yml file when injecting the FeatureChecker in our code:

First, we should register our service:

services:
    InMemoryFeatureChecker:
        public: true
        arguments:
            - '%features%'
Enter fullscreen mode Exit fullscreen mode

Then, using Service Container parameters we set the argument:

parameters:
    features:
        {
            foo: false,
            bar: true
        }
Enter fullscreen mode Exit fullscreen mode

Example

Let's imagine following situation: you have an endpoint that shouldn't be active yet, but it is already implemented:

class SomeController
{
    private FeatureChecker $featureChecker;

    public function __construct(FeatureChecker $featureChecker) 
    {
        $this->featureChecker = $featureChecker;
    }

    public function __invoke(Request $request): JsonResponse
    {
        if (false === $this->featureChecker->isEnabled('foo')) {
            // throw exception to exit endpoint
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Having the interface, you can implement it as better fits to your requirements (from yml files, from redis, mysql...).

Using feature flags, you have a tool to enable / disable easily features of your application.

Our approach has been really basic, but can be extended containing more info about user, quota usage, timestamp to be available from specific moment...

Top comments (5)

Collapse
 
robinbastiaan profile image
Robin Bastiaan

A related way to try to do this is with the use of feature branches. With that approach you would just keep all your features in a separate branch named like feature/my-new-feature and merge them with the main branch when ready. This potentially reduces the complexity of enabling and disabling the feature flags, but it also reduces your ability to run integration tests. And brace yourself for doing some complex code merges...

So this setup seems to me like a good fit for some situations. I also like your idea's with the more complex logic and would like to see that in future blog post. ;)

Collapse
 
rvanlaak profile image
Richard van Laak

A disadvantage of only merging feature branches once ready is that the integration efforts (time needed, costs involved) rise exponentially. In other words, the longer you wait with integrating your feature branch, the harder and riskier it gets for a feature to get merged in the main branch.

And yes, you can regularly merge the main branch back in the feature branch, but that effort is identical to shipping code as often as possible (merging forward) and having a feature flag that is disabled in production. The overhead of coding the feature flag is definitely worth it, and will even allow business to do cool things like releasing features to a small set of testing customers.

In other words, the biggest perk of shipping disabled features that should not get underestimated, is that continuous shipping will give you continuous feedback on side effects and regressions. Knowledge that possibly would be harder to collect outside of a production environment.

The longer deployments of code to production gets postponed, the more likely that the engineer responsible of that code does not know the specifics about it anymore. And, that engineer even could have left the company already.

Collapse
 
mguinea profile image
Marc Guinea

Fully agree! Maybe in more planned situations git branching is better, but as you said, in some situations this approach fits.

I put into my todo list the more complex logic for the next post 🤘

Collapse
 
alexeboswell profile image
Alex Boswell

Great lightweight implementation of feature flags. If you're looking to take feature flags further, check out open source project Flagsmith - github.com/Flagsmith/flagsmith

Collapse
 
mguinea profile image
Marc Guinea

Thanks, I will do it :) looks powerful!