When configuring Laravel Pennant with Laravel Spark, best practices focus on integrating feature flags smoothly into Spark's subscription and user management system to enable controlled feature rollouts, trials, and subscription-based feature gating. Below are detailed best practices based on Laravel Pennant's capabilities and typical Spark usage:
Installation and Basic Setup
- Install Laravel Pennant via Composer:
bash
composer require laravel/pennant
- Publish Pennant's configuration and migration files:
bash
php artisan vendor:publish --provider="Laravel\Pennant\PennantServiceProvider"
- Run migrations to create the `features` table used by Pennant's database driver:
bash
php artisan migrate
This sets up the foundation for storing feature flags persistently[1][2][8].
Defining Feature Flags with Spark Context
- Define feature flags in a service provider such as `AppServiceProvider` or a dedicated feature flag service provider.
- Use the `Feature::define()` method to specify feature flags with logic that considers Spark's subscription and trial status. For example, enable a feature only for users on a trial or specific subscription plans:
php
use Laravel\Pennant\Feature;
public function boot(): void
{
Feature::define('new-dashboard', function ($user) {
// Enable for users on trial or subscribed to a specific Spark plan
return $user->onTrial() || $user->subscribed('premium');
});
}
This approach leverages Spark's subscription methods (`onTrial()`, `subscribed()`) to gate features dynamically[7][8].
Scoping Features Appropriately
- Pennant supports scoping features to users, teams, or globally.
- For Spark, since features often depend on user subscription or team membership, scope feature checks accordingly:
- Use `Feature::for($user)` to check features per user.
- For team-based features, scope to the team model instance.
- To handle global features (not scoped to any user or team), configure Pennant to use a default global scope by calling `Feature::resolveScopeUsing()` in a service provider:
php
Feature::resolveScopeUsing(fn ($driver) => null);
This makes feature checks without explicit scope default to global flags, simplifying feature management[1][9].
Managing Feature Flags in the Database
- Use Pennant's default `database` driver for persistent storage of feature flags, which fits well with Spark's persistent user and subscription data.
- To avoid caching issues during development or when flags need to be evaluated on every request, set the `PENNANT_STORE` environment variable to `array` for in-memory storage or disable query caching as needed[6].
Customizing Feature Scope Serialization
- If you extend Pennant with custom drivers or use complex scopes like Spark's subscription or team models, implement the `FeatureScopeable` contract on those models to customize how scope identifiers are stored and retrieved.
- This ensures compatibility across different Pennant drivers and avoids issues with model serialization[1].
Extending Pennant with Custom Drivers (Optional)
- If you integrate third-party feature flag services or require Redis caching for feature flags, implement a custom Pennant driver by following the `Driver` interface.
- Register the custom driver in a service provider's `boot` method using `Feature::extend()`.
- Configure the driver in `config/pennant.php` to use it in your app[1].
Testing and Deployment
- Write tests for feature flag definitions to verify that features are enabled or disabled correctly based on Spark subscription states.
- Use Pennant's testing helpers to mock feature flags during automated tests.
- Gradually roll out features by toggling flags in the database or via custom admin interfaces.
- Consider integrating feature flag management into Spark's billing or admin dashboards for easier control by product managers.
By following these practices, you ensure Laravel Pennant works effectively with Laravel Spark's subscription and trial system, enabling precise, scope-aware feature flagging that supports safe rollouts, A/B testing, and subscription-based feature access control.
Citations:
[1] https://laravel.com/docs/11.x/pennant
[2] https://www.honeybadger.io/blog/a-guide-to-feature-flags-in-laravel/
[3] https://spark.laravel.com/docs/spark-stripe/upgrade
[4] https://codecourse.com/articles/your-guide-to-every-official-laravel-package-and-service
[5] https://laravel-news.com/feature-flags-with-laravel-pennant
[6] https://stackoverflow.com/questions/77078816/how-to-disable-caching-for-laravel-pennant-in-db
[7] https://github.com/laravel/pennant/issues/52
[8] https://wpwebinfotech.com/blog/laravel-pennant-guide/
[9] https://elliotderhay.com/blog/how-to-make-laravel-pennant-features-that-apply-globally