07.01.2026

Laravel’de Feature Flags ile Güvenli Yayın (Progressive Delivery) ve Hızlı Geri Dönüş

Yeni özellikleri kullanıcı bazında aç/kapat; kademeli yayınla, riskleri azalt, anında rollback yap.

Üretimde “tek seferde yayın” yerine kademeli yayın (progressive delivery) yapmak, hem hatayı sınırlı kitlede yakalamanı hem de gerektiğinde saniyeler içinde geri dönmeni sağlar. Bunu Laravel’de en pratik şekilde feature flag yaklaşımıyla kurabilirsin.

Neden Feature Flag?

  • Risk azaltır: Yeni kod canlıda ama kapalı olabilir.
  • Canary / yüzde bazlı yayın: %5 → %25 → %100.
  • A/B deneyi ve pilot kullanıcılar: Belirli kullanıcılara aç.
  • Anında rollback: Deploy geri almadan özelliği kapat.

Basit Flag Tasarımı: feature_flags Tablosu

Aşağıdaki yapı, “flag aktif mi?”, “kimlere açık?” ve “yüzde kaç kullanıcıya açık?” sorularını karşılar.

// migration (özet)
Schema::create('feature_flags', function ($table) {
    $table->id();
    $table->string('key')->unique();
    $table->boolean('enabled')->default(false);
    $table->unsignedTinyInteger('rollout_percentage')->default(0); // 0-100
    $table->json('allowed_user_ids')->nullable(); // [1,2,3]
    $table->timestamps();
});

Model:

class FeatureFlag extends Model
{
    protected $fillable = ['key','enabled','rollout_percentage','allowed_user_ids'];
    protected $casts = ['allowed_user_ids' => 'array', 'enabled' => 'boolean'];
}

Flag Kontrol Servisi (Cache’li)

DB’ye sürekli gitmemek için flag’i cache’lemek iyi olur.

use Illuminate\Support\Facades\Cache;

class Features
{
    public function enabled(string $key, ?int $userId = null): bool
    {
        $flag = Cache::remember("feature:$key", 30, function () use ($key) {
            return FeatureFlag::query()->where('key', $key)->first();
        });

        if (!$flag || !$flag->enabled) {
            return false;
        }

        // Whitelist: belirli kullanıcılara kesin açık
        if ($userId && is_array($flag->allowed_user_ids) && in_array($userId, $flag->allowed_user_ids, true)) {
            return true;
        }

        // Yüzde bazlı rollout
        $pct = (int) $flag->rollout_percentage;
        if ($pct <= 0) return false;
        if ($pct >= 100) return true;

        // Deterministik dağıtım: aynı userId her zaman aynı sonuca gider
        if (!$userId) return false;

        $hash = crc32($key . ':' . $userId);
        $bucket = $hash % 100; // 0-99

        return $bucket < $pct;
    }

    public function flush(string $key): void
    {
        Cache::forget("feature:$key");
    }
}

Deterministik “bucket” mantığı, kullanıcıların bir gün açık diğer gün kapalı görmesini engeller.

Kullanım Örneği: Controller/Blade

Yeni ödeme akışını sadece %10 kullanıcıya açalım:

public function checkout(Features $features)
{
    $userId = auth()->id();

    if ($features->enabled('new_checkout', $userId)) {
        return view('checkout.v2');
    }

    return view('checkout.v1');
}

Blade içinde:

@if(app(Features::class)->enabled('new_nav', auth()->id()))
  @include('partials.nav_v2')
@else
  @include('partials.nav_v1')
@endif

Operasyonel İpuçları

  • Admin ekranı ile enabled ve rollout_percentage alanlarını anlık yönet.
  • Bir flag değişince ilgili cache’i temizle (ör. Observer veya admin action sonrası flush).
  • Kritik işlerde (ödeme, stok) flag açıkken bile audit log tut.
  • Flag sayısı artarsa: anahtar isimlendirmesi (billing.new_checkout) ve yaşam döngüsü (kapanan flag’leri koddan temizleme) belirle.

Sonuç

Feature flag yaklaşımıyla Laravel projelerinde “deploy = risk” denkleminden çıkıp, kontrollü yayın + hızlı geri dönüş kazanırsın. Küçük bir tablo, cache ve deterministik rollout mantığıyla üretim güvenliğini ciddi şekilde artırmak mümkün.