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:
1composer require ylsideas/feature-flags:^2.0
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:
1# install the config to config/features.php2php artisan vendor:publish — provider=”YlsIdeas\FeatureFlags\FeatureFlagsServiceProvider” — tag=config3 4# install .features.php5php artisan vendor:publish — provider=”YlsIdeas\FeatureFlags\FeatureFlagsServiceProvider” — tag=inmemory-config6 7# install a migration to database/migrations8php artisan vendor:publish — provider=”YlsIdeas\FeatureFlags\FeatureFlagsServiceProvider” — tag=features-migration
Let's first edit our config/features.php
config file and check that the pipeline is as follows:
config/features.php
1'pipeline' => ['database', 'in_memory'],
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:
config/features.php
1'in_memory' => [2 'file' => env('FEATURE_FLAG_IN_MEMORY_FILE', '.features.php'),3 'driver' => 'in_memory',4],
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.
config/features.php
1'database' => [2 'driver' =>' database',3 'cache' => [4 'ttl' => 120,5 ],6'connection' => env('FEATURE_FLAG_DATABASE_CONNECTION'),7'table' => env('FEATURE_FLAG_DATABASE_TABLE', 'features'),8],
As our backup, we will add a default flag value to our .features.php config.
1use Illuminate\Contracts\Foundation\Application; 2 3/** 4 * @returns array<string, bool> 5 */ 6return static function (Application $app): array { 7 return [ 8 'laravel.version' => true, 9 ];10};
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.
1php artisan migrate
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.
resources/views/welcome.blade.php
1@feature('laravel.version')2 <div class=”ml-4 text-center text-sm text-gray-500 sm:text-right sm:ml-0">3 Laravel v{{ Illuminate\Foundation\Application::VERSION }} (PHP v{{ PHP_VERSION }})4 </div>5@endfeature
Doing so means the section will only show when the feature laravel.version is enabled.
Let's run the server using the following:
1php artisan serve
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.
1php artisan feature:on database laravel.version
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.
1php artisan feature:off database laravel.version
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.