Skip to main content
For the basics, see the guide page. This page introduces practical patterns not covered in the official docs.

Team-scoped flags in a multi-tenant SaaS

If you want to manage flags per team (tenant) rather than per individual user, change the default scope to the team.
That’s all it takes for Feature::active('billing-v2') to automatically target the current team. Because everyone on the same team gets the same result, UI consistency is preserved regardless of the member. Here’s an example of a gradual rollout based on a team’s signup date.
To enable only for specific teams (e.g. early access for enterprise customers):

Emergency kill switch (using the before method)

When a bug is discovered in production, you can instantly disable a feature without rolling back code. Adding a before method to a class-based feature makes the check run before the storage value is consulted.
Setting the environment variable FEATURES_NEW_CHECKOUT_DISABLED=true alone stops the feature without touching the database. A kill switch that requires no deploy.
When before returns null, resolve() runs. Returning false immediately treats the flag as inactive. Return null in non-emergency situations.

Scheduled rollouts

The case where you want to automatically enable for all users at a specific date/time. You can implement this in the before method.
Now, once 2025-04-01 passes, the feature automatically ships to all users. No deploy, no DB update, no Artisan command needed.

Dark launch (shadow mode)

A pattern where you run new logic on production data without showing it to users, and compare results to the old logic. If nothing goes wrong, you release simply by flipping the flag.
Once you’ve confirmed the logs show no differences, switch the flag to recommendation-v2 to release.

Collecting A/B test results with events

The official docs mention the FeatureRetrieved event, but do not show a real A/B test aggregation pattern. The FeatureResolved event fires only the first time a feature’s value is resolved. Use it to record a user’s variant assignment.
Record conversions separately when they happen, and you can compute the conversion rate per variant.
Difference between FeatureResolved and FeatureRetrieved: FeatureResolved fires only on the initial evaluation, while FeatureRetrieved fires on every check. Use FeatureResolved for assignment tracking and FeatureRetrieved for pageview tracking.

Scoping in queued jobs

In queued jobs there is no authenticated user, so feature checks can behave unexpectedly. Pass an explicit scope to the job.
You can also evaluate the flag at dispatch time and pass the result to the job.

Admin UI via Artisan commands

Building a simple Artisan command to manage flags lets you operate production flags without deploying.

Safe class refactoring for feature names (the Name attribute)

When renaming a class-based feature, changing the flag name stored in the DB would reset the flag for all users. Use the Name attribute to fix the stored name.
Now you can rename the class freely while keeping the DB data as-is.

Summary

Once you’re comfortable with the basics from the official docs, the following patterns bring out Pennant’s real value.

Laravel Pennant guide

See the guide page for installation and basic usage.
Last modified on July 13, 2026