Skip to content
Back to skills

Laravel Pennant

ASecurity

Use when working with feature flags — Laravel Pennant, gradual rollouts, A/B testing, scope-based flags — even when the user just says 'hide this behind a flag' without naming Pennant.

  • 10 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added June 5, 2026
ai-agentsrustgophpbashtestingdatabase

Security analysis

A100/100

Scanned June 5, 2026

npx -y skills add event4u-app/agent-config --skill laravel-pennant --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Laravel Pennant?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Laravel Pennant
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/event4u-app-laravel-pennant/badge)](https://www.skillsdirectory.com/skills/event4u-app-laravel-pennant)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
model_tier: medium
name: laravel-pennant
description: "Use when working with feature flags — Laravel Pennant, gradual rollouts, A/B testing, scope-based flags — even when the user just says 'hide this behind a flag' without naming Pennant."
domain: engineering
workspaces:
  - engineering
packs:
  - laravel
trust:
  level: professional
install:
  default: false
  removable: true
---

# laravel-pennant

## When to use

Use this skill when working with feature flags:
- Gradual feature rollouts (percentage-based)
- Per-user or per-tenant feature toggling
- A/B testing with feature variants
- Environment-based feature gating

## Procedure: Set up feature flags

1. **Install** — `composer require laravel/pennant`, publish config, run migrations.
2. **Define feature** — Create feature class or use closure-based definition.
3. **Check feature** — Use `Feature::active('feature-name')` in code.
4. **Verify** — Confirm feature is active/inactive for correct scopes. Run tests.

### Installation

```bash
composer require laravel/pennant
php artisan vendor:publish --provider="Laravel\Pennant\PennantServiceProvider"
php artisan migrate
```

## Defining features

### Class-based features (recommended)

```bash
php artisan pennant:feature NewDashboard
```

```php
declare(strict_types=1);

namespace App\Features;

use App\Models\User;
use Illuminate\Support\Lottery;

class NewDashboard
{
    /** Resolve the feature's initial value. */
    public function resolve(User $user): bool
    {
        // Percentage rollout
        return Lottery::odds(1, 10)->choose();  // 10% of users
    }
}
```

### Closure-based features

```php
// In a service provider
use Laravel\Pennant\Feature;

Feature::define('new-dashboard', function (User $user): bool {
    return $user->getCustomer()?->isEarlyAdopter() ?? false;
});

// Rich values (A/B testing)
Feature::define('checkout-button', function (User $user): string {
    return Arr::random(['blue', 'green', 'red']);
});
```

## Checking features

```php
// Boolean check
if (Feature::active('new-dashboard')) {
    // Show new dashboard
}

// Via the user model (HasFeatures trait)
if ($user->features()->active('new-dashboard')) {
    // ...
}

// Rich value
$color = Feature::value('checkout-button');  // 'blue', 'green', or 'red'

// Blade directive
@feature('new-dashboard')
    <x-new-dashboard />
@else
    <x-legacy-dashboard />
@endfeature
```

## Managing features

```php
// Activate for a specific user
Feature::for($user)->activate('new-dashboard');

// Deactivate
Feature::for($user)->deactivate('new-dashboard');

// Activate for everyone
Feature::activateForEveryone('new-dashboard');

// Deactivate for everyone
Feature::deactivateForEveryone('new-dashboard');

// Purge stored values (re-resolve on next check)
Feature::purge('new-dashboard');
```

## Scopes

Features can be scoped to any model, not just users:

```php
// Per-tenant feature
Feature::for($customer)->active('advanced-reporting');

// Define with tenant scope
Feature::define('advanced-reporting', function (Customer $customer): bool {
    return $customer->getPlan() === 'enterprise';
});
```

## Drivers

| Driver | Storage | Use case |
|---|---|---|
| `database` | DB table | Production — persistent, shared across servers |
| `array` | In-memory | Testing — no persistence |

```php
// config/pennant.php
'default' => env('PENNANT_STORE', 'database'),
```

## Eager loading

```php
// Prevent N+1 when checking features for multiple users
Feature::for($users)->loadAll();

// Load specific features
Feature::for($users)->load(['new-dashboard', 'advanced-reporting']);
```

## Core rules

- **Use class-based features** for anything non-trivial — they're testable and discoverable.
- **Scope to the right model** — user, customer, or team depending on the feature.
- **Eager load** when checking features for collections of users.
- **Purge after full rollout** — remove the flag once 100% of users have the feature.
- **Use `array` driver in tests** — prevents test pollution.
- **Clean up old flags** — feature flags are temporary, not permanent config.

## Output format

1. Feature flag definition with scope and resolve logic
2. Integration in controllers/services using Feature::active()

## Auto-trigger keywords

- feature flag
- feature toggle
- Pennant
- gradual rollout
- A/B test
- feature gate

## Gotcha

- Feature flags in database driver require migration — don't forget `php artisan pennant:purge` for cleanup.
- The model tends to check flags without a scope — always pass the authenticated user or a default scope.
- Don't nest feature flag checks — it makes the logic impossible to reason about.

## Do NOT

- Do NOT leave feature flags forever — remove them after full rollout.
- Do NOT use feature flags for permanent configuration — use config files.
- Do NOT check features in tight loops without eager loading.
- Do NOT forget to purge stored values when changing the resolve logic.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.