DEV Community

Peter Fox
Peter Fox

Posted on • Originally published at Medium on

Implementing Feature Flags


Photo by Glen Rushton on Unsplash

Feature flags are not a new concept. You might already have what is effectively a feature flag within your application. One of the often most referenced pieces on Feature Flags is by Martin Fowler, written back in 2017.

His article describes feature toggles, also known as feature flags. You wouldn’t be blamed for being confused looking at the contents and not understanding where to start.

Several cloud services exist, but they’re not easy to start with. As an avid Laravel Developer, I decided to make a package in 2019 to solve many of those difficulties so you can quickly start building an application with feature flags.

To get started, let’s cover some basics.

What is a feature flag?

A feature flag is no different from adding any other application functionality. The flag hides functionality until it’s ready for customers to use. Sometimes this is also known as a feature toggle.

What makes feature flags worthwhile?

Feature flags help you separate feature development and feature deployment. When you build a feature and use source control, you will have to wait to merge new functionality until all parts of the new functionality are ready to be released to customers and visitors.

This can be problematic and leads to large and complex pull requests. Then when you think you’re ready to merge, another pull request goes in first, causing a round of complex conflicts that need to be resolved.

That puts your plans to deploy on time at risk.

For many developers, this is just how it is, right? You make code and merge it when it’s ready for viewing eyes.

This mindset, while understandable, needs to be revised for building modern web applications.

Feature flags can change that. At the same time, they bring additional complexity once you try to implement them at scale. This was my reason for creating Feature Flags for Laravel to remove some of the upfront work required to avoid that complexity.

Using Feature Flags for Laravel

I created a package for this back in 2019. You can manage feature flags very quickly by using Laravel’s configs. That said, it can become hard to manage and often to change an application’s environment variables to affect configs, which means you have to run a new deployment even if the code is the same.

Instead, using the Laravel Feature Flags package, we can configure things to rely on the database and fall back to a config file. The package provides the API for making it easier to swap around persistence mechanisms with minimal fuss.

Installing and Configuring

First, we’ll take a default app with the familiar Laravel Welcome page. We want to hide the application’s version number behind a flag. Doing this allows us to change the deployment of this vital information only when needed.

To begin, we will install the package using composer:

composer require ylsideas/feature-flags:^2.0
Enter fullscreen mode Exit fullscreen mode

After this, we need to publish a few files, and because we intend to store our flags in the database and a configuration file, we need to generate the migration for our flags table and a .features.php file. We can do that with the following commands:

# install the config to config/features.php
php artisan vendor:publish — provider=”YlsIdeas\FeatureFlags\FeatureFlagsServiceProvider” — tag=config
# install .features.php
php artisan vendor:publish — provider=”YlsIdeas\FeatureFlags\FeatureFlagsServiceProvider” — tag=inmemory-config
# install a migration to database/migrations
php artisan vendor:publish — provider=”YlsIdeas\FeatureFlags\FeatureFlagsServiceProvider” — tag=features-migration
Enter fullscreen mode Exit fullscreen mode

Let’s first edit our config/features.php config file and check that the pipeline is as follows:

‘pipeline’ => [‘database’, ‘in_memory’],
Enter fullscreen mode Exit fullscreen mode

By choosing the following gateways, we’re telling the pipeline to look at the database and then the .features.php file as a backup.

Now we need to check each gateway. For the in-memory gateway, the settings should be as follows:

‘in_memory’ => [
 ‘file’ => env(‘FEATURE_FLAG_IN_MEMORY_FILE’, ‘.features.php’),
 ‘driver’ => ‘in_memory’,
],
Enter fullscreen mode Exit fullscreen mode

We’re going to change the database gateway and include some caching. A 2-minute cache should do, which is 120 seconds. This will mean that if a feature is accessed a few times within that time frame, the same result will be returned, saving our database from additional queries to run.

‘database’ => [
 ‘driver’ =>’ database’,
 ‘cache’ => [
 ‘ttl’ => 120,
 ],
 ‘connection’ => env(‘FEATURE_FLAG_DATABASE_CONNECTION’),
 ‘table’ => env(‘FEATURE_FLAG_DATABASE_TABLE’, ‘features’),
],
Enter fullscreen mode Exit fullscreen mode

As our backup, we will add a default flag value to our .features.php config.

<?php

use Illuminate\Contracts\Foundation\Application;

/**
 * @returns array<string, bool>
 */
return static function (Application $app): array {
 return [
 ‘laravel.version’ => true,
 ];
};
Enter fullscreen mode Exit fullscreen mode

These are the values we can commit into our repository as defaults then.

We quickly need to run the migrations for the database. If you’re working with a new Laravel app, we can use SQLite.

php artisan migrate
Enter fullscreen mode Exit fullscreen mode

Let’s add a flag

Now to keep things simple, let’s add our initial flag. For this, we’ll open up the welcome.blade.php file and edit the part showing the Laravel version.

We can wrap the version in a blade directive made available by the package.

@feature(‘laravel.version’)
<div class=”ml-4 text-center text-sm text-gray-500 sm:text-right sm:ml-0">
 Laravel v{{ Illuminate\Foundation\Application::VERSION }} (PHP v{{ PHP_VERSION }})
</div>
@endfeature
Enter fullscreen mode Exit fullscreen mode

Doing so means the section will only show when the feature laravel.version is enabled.

Let’s run the server using the following:

php artisan serve
Enter fullscreen mode Exit fullscreen mode

And now, we can go to the default Welcome page to see if the version is missing. Success!

Now we can run the following artisan command, again available from the package and see if it affects the Welcome page.

php artisan feature:on database laravel.version
Enter fullscreen mode Exit fullscreen mode

We may have to wait for a second to see the result.

We only need to run the command with the off value and disable the flag from running. Again this might take up to two minutes to show and change.

php artisan feature:off database laravel.version
Enter fullscreen mode Exit fullscreen mode

Conclusion

Feature flags might not be necessary for those working on a product with one or two other people, but beyond that, they can become a critical tool in helping you deliver features on time.

This only scratches the surface. The real power starts when you can begin building flags that will be turned on and off per user or team. Once we reach this point, we will need to start using the gate gateway in the package or build a custom gateway for Feature Flags for Laravel.

This brings me to talking about the next step in my journey to helping others build with feature flags, a premium package to support managing the deployment and rollout of features to specific users and more.

If you want to check out the finished code from this article, you can always check out the demo on GitHub. You can find the repository for Feature Flags for Laravel on GitHub and the dedicated documentation website for FFfL.

I’m Peter Fox, a UK software developer with a decade of experience with PHP and Laravel. I’ve started work on a new project. Flagfox for Laravel will build upon my established work creating open-source packages to help developers add feature flags to their applications. We currently have a waiting list for those interested in learning more.

Top comments (0)