Hire Laravel developers with AI expertise at $20/hr. Get started in 48 hours.

Simple Feature Flags for Laravel with Laravel Toggle

Published on by

Simple Feature Flags for Laravel with Laravel Toggle image

Laravel Toggle is a lightweight feature flag package focused on global on/off switches. Laravel's first-party Pennant package is built for user-segmented rollouts and A/B testing; Laravel Toggle is intentionally simpler and skips user resolution entirely, leaving you with flags controlled by .env, the database, or a mix of the two.

Installation

The package requires PHP 8.2+ and Laravel 11, 12, or 13.

composer require offload-project/laravel-toggle
 
php artisan vendor:publish --tag=toggle-config

If you plan to use the database driver, publish and run the migrations:

php artisan vendor:publish --tag=toggle-migrations
php artisan migrate

Defining and Checking Toggles

Flags live in config/toggle.php and can be backed by environment variables:

'flags' => [
'comments' => env('TOGGLE_COMMENTS', true),
'related-articles' => env('TOGGLE_RELATED_ARTICLES', false),
],

You check them through the Toggle facade. An article controller that conditionally loads relationships can branch on a flag without polluting the query:

use OffloadProject\Toggle\Facades\Toggle;
 
class ArticleController
{
public function show(string $slug)
{
$article = Article::where('slug', $slug)
->when(Toggle::active('comments'), fn ($q) => $q->with('comments.author'))
->firstOrFail();
 
return view('articles.show', [
'article' => $article,
'related' => Toggle::active('related-articles')
? RelatedArticles::for($article)
: collect(),
]);
}
}

Toggle::inactive() is handy for guarding behaviour that should only run while a feature is off, like falling back to a plain email digest when the richer newsletter pipeline is disabled:

if (Toggle::inactive('newsletter-v2')) {
Mail::to($subscriber)->queue(new WeeklyDigest($articles));
}

Blade templates get dedicated directives so you don't have to wrap conditionals manually. A typical case is rendering a comment thread under an article only while the feature is enabled:

@toggle('comments')
<livewire:article.comments :article="$article" />
@elsetoggle
<p class="text-sm text-gray-500">Comments are closed on this post.</p>
@endtoggle

If you prefer type-safe identifiers, you can use a backed enum anywhere a flag name is accepted. Centralising flag names in a Feature enum keeps them autocompletable and easy to grep when it is time to retire one:

enum Feature: string
{
case Comments = 'comments';
case RelatedArticles = 'related-articles';
case Paywall = 'paywall';
}
 
if (Toggle::active(Feature::Paywall) && $article->isPremium()) {
return view('articles.paywall', compact('article'));
}

Drivers

Laravel Toggle ships with two storage drivers, selected through TOGGLE_DRIVER:

TOGGLE_DRIVER=config # Read-only, uses config/toggle.php flags
TOGGLE_DRIVER=database # Read-write, falls back to config

The config driver is read-only at runtime because its values are sourced from environment variables. The database driver checks the database first and falls back to the config value if no record exists, so config defaults still apply until you override them.

You can also mix both drivers in the same application by listing database-driven flags separately:

'flags' => [
'comments' => env('TOGGLE_COMMENTS', true),
'related-articles' => env('TOGGLE_RELATED_ARTICLES', false),
],
 
'database_flags' => [
'breaking-news-banner',
'newsletter-signup-modal',
],

Flags in database_flags always use the database driver (with config fallback), flags in flags stay read-only, and any unlisted flag falls back to the global driver. This lets stable flags stay in .env while operational flags can be flipped without a deploy.

Runtime Control and Caching

When the database driver is active, you can enable or disable flags at runtime. An editor publishing breaking news might flip a banner on from an admin screen without touching .env or shipping a deploy:

Toggle::enable('breaking-news-banner');
 
// Later, once the story is no longer front-page
Toggle::disable('breaking-news-banner');
 
// Or remove the override entirely and fall back to the config default
Toggle::delete('breaking-news-banner');
 
Toggle::all(); // ['breaking-news-banner' => true, 'newsletter-signup-modal' => false, ...]

Lookups are cached, and you can tune the cache store and TTL through environment variables:

TOGGLE_CACHE_ENABLED=true
TOGGLE_CACHE_STORE=redis
TOGGLE_CACHE_TTL=3600

The bundled Toggle Eloquent model clears the cache automatically when records are saved or deleted, and you can also flush it manually with Toggle::forgetCache('name') or Toggle::flushCache().

For undefined flags, the package's behaviour is configurable: return false, return true, or throw a ToggleNotFoundException so missing flags fail loudly during development.

TOGGLE_DEFAULT=false
TOGGLE_DEFAULT=true
TOGGLE_DEFAULT=exception

Inertia and Artisan

If your frontend uses Inertia, the included ShareTogglesWithInertia middleware exposes every toggle as a flags prop. This allows your Vue, React, or Svelte components to conditionally render features without requiring additional API calls:

use OffloadProject\Toggle\Middleware\ShareTogglesWithInertia;
 
->withMiddleware(function (Middleware $middleware) {
$middleware->web(append: [
ShareTogglesWithInertia::class,
]);
})
const { flags } = usePage().props
 
if (flags.breakingNewsBanner) {
showBanner()
}

The package also provides a handful of Artisan commands for day-to-day work, including toggle:list to inspect every defined flag and its current state, toggle:create to scaffold a new flag in config/toggle.php and .env (with optional --active and --db flags), and toggle:cache-clear to flush either all toggle caches or a single entry.

You can learn more and view the source code on GitHub.

Yannick Lyn Fatt photo

Staff Writer at Laravel News and Full stack web developer.

Cube

Laravel Newsletter

Join 40k+ other developers and never miss out on new tips, tutorials, and more.

image
Laravel Code Review

Get expert guidance in a few days with a Laravel code review

Visit Laravel Code Review
Shift logo

Shift

Running an old Laravel version? Instant, automated Laravel upgrades and code modernization to keep your applications fresh.

Shift
Get expert guidance in a few days with a Laravel code review logo

Get expert guidance in a few days with a Laravel code review

Expert code review! Get clear, practical feedback from two Laravel devs with 10+ years of experience helping teams build better apps.

Get expert guidance in a few days with a Laravel code review
PhpStorm logo

PhpStorm

The go-to PHP IDE with extensive out-of-the-box support for Laravel and its ecosystem.

PhpStorm
Harpoon: Next generation time tracking and invoicing logo

Harpoon: Next generation time tracking and invoicing

The next generation time-tracking and billing software that helps your agency plan and forecast a profitable future.

Harpoon: Next generation time tracking and invoicing
SerpApi logo

SerpApi

Access real-time search engine results through a simple API—no more scraping headaches! Use it for AI applications, SEO tools, product research, travel information, and more

SerpApi
Laravel Cloud logo

Laravel Cloud

Easily create and manage your servers and deploy your Laravel applications in seconds.

Laravel Cloud
Kirschbaum logo

Kirschbaum

Providing innovation and stability to ensure your web application succeeds.

Kirschbaum
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS Starter Kit

SaaSykit is a Multi-tenant Laravel SaaS Starter Kit that comes with all features required to run a modern SaaS. Payments, Beautiful Checkout, Admin Panel, User dashboard, Auth, Ready Components, Stats, Blog, Docs and more.

SaaSykit: Laravel SaaS Starter Kit
Acquaint Softtech logo

Acquaint Softtech

Acquaint Softtech offers AI-ready Laravel developers who onboard in 48 hours at $3000/Month with no lengthy sales process and a 100 percent money-back guarantee.

Acquaint Softtech
Tinkerwell logo

Tinkerwell

The must-have code runner for Laravel developers. Tinker with AI, autocompletion and instant feedback on local and production environments.

Tinkerwell
Lucky Media logo

Lucky Media

Get Lucky Now - the ideal choice for Laravel Development, with over a decade of experience!

Lucky Media

The latest

View all →
Manage Laravel Cloud Deployments Inside PhpStorm image

Manage Laravel Cloud Deployments Inside PhpStorm

Read article
Piper: Laravel-Style Array and String Helpers for PHP's Pipe Operator image

Piper: Laravel-Style Array and String Helpers for PHP's Pipe Operator

Read article
Storage Cache Store in Laravel 13.10.0 image

Storage Cache Store in Laravel 13.10.0

Read article
Laravel MongoDB Full-Text Search tutorial: The Art of the Relevancy image

Laravel MongoDB Full-Text Search tutorial: The Art of the Relevancy

Read article
Drag-and-Drop Sorting for Eloquent Models with Reorderable for Laravel image

Drag-and-Drop Sorting for Eloquent Models with Reorderable for Laravel

Read article
Ship AI with Laravel: Real-Time Streaming Chat UI with Livewire image

Ship AI with Laravel: Real-Time Streaming Chat UI with Livewire

Read article