ViraStack
  • Academy
  • About
  • Support
HomeSourcesContribute
ViraStack

A frontend ecosystem: free guides, project templates, AI rules, and form components.

Products

  • ViraStack Start
  • ViraStack AI
  • ViraStack Mask
  • ViraStack Password
  • ViraStack Guide

Explore

  • Academy
  • About
  • Brand
  • Support

© 2026 ViraStack.

Open source · MIT

Production'a Hazırlık

06 / 08

Feature flag ve yayın stratejisi

Deploy ile yayını ayırmak, flag türleri ve taşıma maliyeti, Flags SDK ile sunucuda değerlendirilen bir flag, kullanıcıyı sabit kovaya yerleştirerek yüzdeli açılış, canary ve blue-green yayın, geri alma ve flag'leri test etmek.

Deploy Etmek ile Yayınlamak Farklıdır

Deploy, yeni kodun sunucuya gitmesidir. Yayın (release), kullanıcının yeni özelliği görmesidir. Çoğu projede ikisi aynı andadır: kod canlıya çıktığı an herkes yeni özelliği görür ve bir sorun çıkarsa tek çare geri deploy etmektir.

Feature flag (özellik bayrağı) ikisini ayırır. Kod canlıdadır ama özellik kapalıdır; kimin ne zaman göreceğine bir yapılandırma karar verir. Sorun çıkarsa flag kapatılır, deploy gerekmez.

Flag Türleri

Pete Hodgson'ın martinfowler.com'da yayımlanan yazısı flag'leri ne kadar yaşadıklarına ve ne kadar dinamik olduklarına göre dörde ayırır:1

TürAmaçÖmür
Yayın (release)Yarım kalmış ya da yeni bir özelliği kapalı tutarak canlıya çıkarmakGünler, birkaç hafta
Deney (experiment)A/B testi; kullanıcıları gruplara ayırıp davranışı karşılaştırmakAnlamlı sonuç alınana kadar
Operasyon (ops)Yük altında ağır bir özelliği kapatmak; "acil durum anahtarı"Kısa ya da kalıcı
İzin (permissioning)Özelliği yalnızca belirli kullanıcılara açmak (beta, premium, iç ekip)Uzun, çoğu zaman kalıcı

Hodgson'ın en önemli uyarısı maliyetle ilgilidir: flag'ler bir envanterdir ve taşıma maliyeti vardır. Her flag kodda bir dal, test edilmesi gereken bir kombinasyon ve unutulursa kalıcı bir karmaşıklık demektir. Yayın flag'leri işini bitirince silinmelidir.1

Do

  • Her flag'e bir sahip ve bir silinme tarihi verin.

  • Özellik yüzde 100'e ulaşıp bir süre sorunsuz çalıştıysa flag'i ve eski kodu silen pull request'i açın.

Flags SDK

Flags SDK, Next.js ekibinin açık kaynak flag kütüphanesidir; herhangi bir flag sağlayıcısıyla ya da kendi kurallarınızla çalışır.2

$ pnpm add flags

Her flag bir fonksiyon olarak tanımlanır:23

// lib/flags.ts
import "server-only";
import { flag } from "flags/next";
import { getEnv } from "./env";
import { isInRollout } from "./rollout";
import { SESSION_COOKIE } from "./session";
import { readSession } from "./store";

type Entities = { user?: { id: string } };

export const orderSummaryFlag = flag<boolean, Entities>({
  key: "order-summary",
  description: "Sipariş listesinin üstünde adet ve toplam tutar özeti",
  defaultValue: false,
  options: [
    { value: false, label: "Kapalı" },
    { value: true, label: "Açık" },
  ],
  identify({ cookies }) {
    const session = readSession(cookies.get(SESSION_COOKIE)?.value);
    return session ? { user: { id: session.user.id } } : undefined;
  },
  decide({ entities }) {
    if (!entities?.user) return false;
    return isInRollout(entities.user.id, "order-summary", getEnv().ORDER_SUMMARY_ROLLOUT);
  },
});
  • key flag'in kimliğidir.

  • defaultValue flag değerlendirilemezse kullanılır. Varsayılanın tanımda olması her çağrıda aynı varsayılanı garanti eder.3

  • identify kim için karar verildiğini bulur. Normalize edilmiş headers ve cookies alır; döndürdüğü varlıklar decide'a geçer.4

  • decide ne döneceğine karar verir.

Hodgson'ın yazısı karar noktasını (kodda flag'in sorulduğu yer) karar mantığından (flag'in neye göre açıldığı) ayırmayı önerir.1 Flags SDK'nın identify ve decide ayrımı tam olarak budur. Kural değişince çağıran kod değişmez.

Kullanımı:

// app/orders/page.tsx
async function OrdersSection() {
  const user = await getCurrentUser();
  const showSummary = await orderSummaryFlag();

  return <OrdersPanel canCancel={user.role === "admin"} showSummary={showSummary} />;
}

Her flag aynı biçimde çağrılır: await orderSummaryFlag(). Editörde "Tüm referansları bul" ile flag'in nerelerde kullanıldığı görünür; silme günü geldiğinde bu çok işe yarar.3

Neden Sunucuda?

Flags SDK flag'lerin sunucuda değerlendirilmesini savunur. Tarayıcıda değerlendirilen bir flag, değeri ağdan gelene kadar ya bir yükleniyor göstergesi ya da tahmini bir sürüm göstermek zorundadır; değer farklı çıkarsa sayfa kayar.5 Sunucuda değerlendirilen flag'de sunucu yalnızca doğru sürümü gönderir.

Bedeli: flag cookie okuduğu için sayfanın o kısmı isteğe bağlı (dinamik) olur. Bu projede flag zaten oturum okuyan, Suspense içindeki bir bileşende çağrılır (bkz. Veri çekme ve streaming). Statik kalması gereken pazarlama sayfaları için SDK'nın proxy ile önceden hesaplama (precompute) kalıpları vardır.5

Yüzdeli Açılış

"Kullanıcıların yüzde 10'una aç" demek kolaydır, doğru yapmak değil. Math.random() < 0.1 her istekte farklı sonuç verir: kullanıcı sayfayı yenileyince özellik kaybolur.

Doğrusu kullanıcıyı sabit bir kovaya yerleştirmektir. Kullanıcı kimliğinin özeti (hash) 0-99 arasında bir sayıya çevrilir; sayı yüzdeden küçükse kullanıcı içeridedir:

// lib/rollout.ts
export function rolloutBucket(id: string, salt: string): number {
  let hash = 0x811c9dc5;
  for (const char of `${salt}:${id}`) {
    hash ^= char.codePointAt(0)!;
    hash = Math.imul(hash, 0x01000193);
  }
  return (hash >>> 0) % 100;
}

export function isInRollout(id: string, salt: string, percentage: number): boolean {
  return rolloutBucket(id, salt) < percentage;
}

Bu yöntemin üç özelliği, projede birer testle doğrulanır:

  1. Kalıcı: Aynı kullanıcı her istekte aynı kovaya düşer.

  2. Dengeli: 10.000 kullanıcıda yüzde 30'luk açılış yaklaşık yüzde 30'u içerir.

  3. Büyüyen: Yüzde 10'dan 30'a çıkınca önceden içeride olan kimse dışarıda kalmaz; çünkü kovası 10'dan küçük olan, 30'dan da küçüktür.

salt (tuz) her flag'e farklı bir dağılım verir. Tuz olmasaydı, her yeni özelliği ilk görenler hep aynı yüzde 10 olurdu.

Tip

Projede yüzde, ORDER_SUMMARY_ROLLOUT ortam değişkeninden gelir; değiştirmek sunucunun yeniden başlatılmasını gerektirir. Gerçek projelerde bu değer bir flag sağlayıcısında (LaunchDarkly, Statsig, GrowthBook ya da Vercel Flags gibi) tutulur ve anında değişir. Flags SDK'nın sağlayıcı adaptörleri bunun içindir; decide'ın içi değişir, çağıran kod değişmez.2

Canary ve Blue-Green

Flag'ler özellik düzeyinde çalışır. Bir de deploy düzeyinde stratejiler vardır:

Canary yayın. Danilo Sato'nun martinfowler.com'daki tarifine göre yeni sürüm önce trafiğin küçük bir kısmına verilir. Sorun yoksa pay kademeli olarak artırılır, sorun çıkarsa trafik eski sürüme döner.6 Adını madencilerin zehirli gazı erken fark etmek için ocağa götürdüğü kanaryadan alır.

Blue-green deploy. Martin Fowler'ın anlattığı yöntemde iki aynı canlı ortam vardır. Biri trafiği alırken yeni sürüm diğerine kurulur ve test edilir; sonra yönlendirici trafiği yeni ortama çevirir. Geri almak için yönlendiriciyi eski ortama çevirmek yeterlidir.7

StratejiNe kontrol edilirGeri alma
Feature flagTek bir özellik, kullanıcı bazındaFlag'i kapatmak, saniyeler
CanaryTüm sürüm, trafik yüzdesiyleTrafiği eski sürüme çevirmek
Blue-greenTüm sürüm, tek seferdeYönlendiriciyi eski ortama çevirmek

Vercel gibi platformlar her deploy'u ayrı tutar ve canlıyı eski bir deploy'a anında döndürmeye izin verir. Kendi altyapınızda bu, eski imajı yeniden başlatmak demektir; imajları commit SHA'sıyla etiketlemenin bir sebebi de budur (bkz. CI/CD).

Warning

Kademeli yayın sırasında eski ve yeni sürüm aynı anda çalışır. Veritabanı şeması değişiyorsa yeni sürüm eski şemayla, eski sürüm yeni şemayla da çalışabilmelidir. Next.js tarafındaki karşılığı sürüm farkıdır (version skew); deploymentId bunun için vardır (bkz. Deploy seçenekleri).

Açılışı İzlemek

Yüzdeyi artırmadan önce sorun: hata oranı arttı mı? Gecikme değişti mi? Hata izleme ve loglarda flag'in açık olduğu kullanıcıları ayırabilmek için flag değerini kayıtlara ekleyin:

logger.info({ event: "orders_viewed", userId: user.id, orderSummary: showSummary }, "Siparişler görüntülendi");

Tipik bir açılış takvimi: iç ekip, yüzde 1, yüzde 10, yüzde 50, yüzde 100. Her adımda metriklere bakın; bir sonraki adıma geçmek bir karardır, otomatik değildir.

Flag'leri Test Etmek

Flag'li bir özelliğin iki hali vardır ve ikisi de test edilmelidir.

Saf fonksiyon olarak. rolloutBucket ve isInRollout tarayıcı gerektirmez; projede tests/rollout.spec.ts bunları doğrular. Gerçek bir projede bu testler Vitest gibi bir birim test aracında daha hızlı çalışır.

Uçtan uca. Projede Playwright sunucuyu ORDER_SUMMARY_ROLLOUT=100 ile başlatır ve özetin göründüğünü doğrular (bkz. Playwright):

// playwright.config.ts
webServer: {
  command: "npm run build && npm run start",
  url: "http://localhost:3000/login",
  env: { PORT: "3000", APP_ENV: "local", APP_VERSION: "test", ORDER_SUMMARY_ROLLOUT: "100" },
},

Flags SDK test başına değer vermek için şifreli bir override cookie'si de destekler. Bunun için FLAGS_SECRET gerekir; aynı secret Vercel Toolbar'ın Flags Explorer'ı ile kendi oturumunuzda flag değiştirmeye de yarar.8

Kendin Dene

  • Projenize bir yayın flag'i ekleyin. Kapalıyken eski, açıkken yeni bileşeni gösterin.

  • rolloutBucket'ı 10.000 kimlikle çalıştırın ve yüzde 10, 30, 50 için dağılımı ölçün.

  • Tuzu çıkarın ve iki farklı flag için içeride kalan kullanıcıların aynı olduğunu görün.

  • Projenizdeki flag'leri listeleyin. Hangisi yüzde 100'de ve hâlâ kodda?

Detaylı Öğrenmek İçin

  • Yazı: Pete Hodgson, "Feature Toggles (aka Feature Flags)"; flag türleri, karar noktası ve taşıma maliyeti.1

  • Resmi doküman: Flags SDK, "Quickstart" ve "Flags as Code"; Next.js'te flag tanımlamak.23

  • Yazı: Danilo Sato, "Canary Release"; kademeli trafikle yayın.6

Kaynaklar

  • 1ArticlePete Hodgson

    : — 9 Ekim 2017. Yayın, deney, operasyon ve izin flag'leri, karar noktasını mantıktan ayırmak, taşıma maliyeti.

  • 2DocsFlags SDK: Quickstart

    Next.js'te kurulum, flag tanımlamak ve App Router'da kullanmak.

  • 3DocsFlags SDK: Flags as Code

    Flag'lerin fonksiyon olması, tanımdaki varsayılan değer ve bağlamın tanımda kurulması.

  • 4DocsFlags SDK: Evaluation Context

    `identify`, tipli varlıklar, normalize edilmiş headers ve cookies.

  • 5DocsFlags SDK: Server-side vs Client-side

    Sunucuda değerlendirmenin gerekçesi ve statik sayfa kalıpları.

  • 6ArticleDanilo Sato

    : — 25 Haziran 2014. Yeni sürümü trafiğin küçük bir kısmıyla denemek.

  • 7ArticleMartin Fowler

    : — 1 Mart 2010. İki canlı ortam ve yönlendiriciyle geçiş ve geri alma.

  • 8DocsFlags SDK: End-to-End Tests

    Playwright ile override cookie'si ve `FLAGS_SECRET`.

Edit this page

Last updated: October 22, 2026

Previous step05. LoglamaNext step07. Yayın öncesi kontrol listesi