Flagi funkcji i zwolnienie funkcji
Flaga funkcji (FF) to warunek zarządzany, który umożliwia/wyłącza zachowanie systemu bez uwalniania kodu. Flagi pozwalają: bezpiecznie rozwinąć funkcje, docelowe grupy użytkowników/rynków/najemców, szybko wyłączyć komponenty problematyczne, przeprowadzić eksperymenty i skonfigurować parametry w czasie trwania.
Główne cele:- Zmniejszyć promień wybuchu dla uwolnień.
- Oddzielne wdrożenie i aktywacja.
- Umożliwia przejrzyste zarządzanie zmianami z audytem, SLO i jednym kliknięciem rollback.
1) Rodzaje flag i kiedy je stosować
Flag wydania - stopniowe włączenie nowej funkcji (ciemne → kanaryjskie → ramp-up → 100%).
Ops/kill-switch - natychmiastowe odłączenie zależności (dostawca, podsystem, ciężkie obliczenia).
Eksperyment (A/B, multi-variant) - podział ruchu na warianty (wagi, lepkie kubełkowanie).
Zezwolenie/Uprawnienie - dostęp do funkcji według roli/planu/jurysdykcji.
Zdalny Config - parametry zachowania (próg, timeout, formuła) z flagi/konfiguracji.
Flagi migracyjne - przełączanie schematów/ścieżek danych (przejście do nowego indeksu/DB/punktu końcowego).
Anty-wzór: ta sama flaga „o wszystkim” - podzielona na funkcję, przełącznik comp i parametry.
2) Model danych bandery (minimum)
yaml flag:
key: "catalog. new_ranker"
type: "release" # release ops kill experiment permission config migration description: "New Directory Ranking"
owner: "search-team@company"
created_at: "2025-10-01T10:00:00Z"
ttl: "2026-01-31" # delete deadline after 100% enable rules:
- when:
tenant_id: ["brand_eu","brand_latam"]
region: ["EE","BR"]
user_pct: 10 # progressive percentage then: "on"
- when:
kyc_tier: ["unverified"]
then: "off"
variants: # for experiments
- name: "control"; weight: 50
- name: "v1"; weight: 30
- name: "v2"; weight: 20 payload:
v1:
boost_freshness: 0. 3 boost_jackpot: 0. 2 v2:
boost_freshness: 0. 2 boost_jackpot: 0. 4 prerequisites: # dependent flags/schema versions
- key: "catalog. index_v2_ready"
must_be: "on"
audit:
require_ticket: true change_window: "09:00-19:00 Europe/Kyiv"
safeguards:
max_rollout_pct: 50 # stop threshold auto_rollback_on:
p95_ms: ">200"
error_rate: ">2%"
3) Ocena i ukierunkowanie
Клибтардетина: 'tenant _ id, region/licencja, waluta, kanał, locale, role, plan, device, user_id, cohort, kyc_tier, experiment_bucket'.
Kolejność oceny: warunki wstępne → odmowa reguł → zezwala na zasady → domyślne.
Sticky bucketing: dla eksperymentów, hash stabilny identyfikator (na przykład „hash (user_id, flag_key)”) tak, że użytkownik zawsze dostaje jedną opcję.
ts result = evaluate(flag, context) // pure function if (!prereqs_ok(result)) return OFF if (deny_match(result, ctx)) return OFF if (allow_match(result, ctx)) return resolve_variant_or_on(result, ctx)
return flag. default
4) Dystrybucja i architektura FF
Opcje:- SDK po stronie serwera (zalecane): źródła prawdy i pamięci podręcznej w plecach; ujednolicenie logiki.
- Ocena krawędzi/CDN: szybkie ukierunkowanie na obwód (gdzie nie ma PII/tajemnic).
- Klient-side SDK: gdy potrzebujesz personalizacji interfejsu użytkownika, ale tylko z minimalnym kontekstem i bez wrażliwych zasad.
- Config-as-Code: przechowywanie flag w repozytorium, walidacja CI, rollout przez CD.
- Startup bootstrap + aktualizacje strumieniowe (SSE/gRPC) + fallback do ostatniego migawki.
- Flagi „świeżości” SLA: p95 ≤ 5 s.
5) Strategie uwolnienia
5. 1 Dark Launch
Funkcja jest włączona, ale niewidoczna dla użytkownika; zbierać mierniki i błędy.
5. 2 Kanaryjskie
Uwzględniamy 1-5% ruchu w jednej jurysdykcji/najemcy; monitor p95/p99, błędy, konwersja.
Warunki zatrzymania - uruchamianie progu autokatoffu za pomocą mierników.
5. 3 Stopniowe wprowadzanie
10% → 25% → 50% → 100% zaplanowane z ręczną/automatyczną weryfikacją.
5. 4 Cień/lusterko
Duplikujemy żądania do nowej ścieżki (bez widocznego efektu) i porównujemy wyniki/opóźnienia.
5. 5 niebieski/zielony + FF
Wdrażamy dwie wersje; flaga kieruje ruchem i przełącza zależności według segmentów.
6) Zależność i spójność między usługami
Użyj warunków wstępnych i „flagi zdrowia” gotowości: wskaźnik jest zbudowany, migracja jest zakończona.
Koordynacja poprzez wydarzenia: „Zmieniono (flag_key, zakres, new_state)”.
1. enable reading-path → 2) check metrics → 3) enable write/side-effects.
- Zamówienia na usługi: niewykonanie zobowiązania musi być bezpieczne dla awarii OFF.
7) Obserwowalność i SLO
Mierniki na flagę/wariant/segment:- 'flag _ eval _ p95 _ ms', 'errors _ rate', 'config _ freshness _ ms'.
- Wskaźniki biznesowe: 'ctr', 'conversion', 'ARPU', 'retention', barierki (np. Incydenty RG).
- Automatyczne progi SLO dla autokatopy.
Logs/tracing: dodaj 'flag _ key', 'variant', 'decision _ source' (serwer/edge/client), 'context _ hash'.
Deski rozdzielcze: „drabina” z progami, błędy mapy ciepłowniczej według segmentów.
8) Bezpieczeństwo i zgodność
Minimalizacja PII w kontekście.
RLS/ACL: kto może zmienić jakie flagi (według domeny/rynku).
Godzinne okna zmian (zmiana okien) i „podwójne potwierdzenie” dla wrażliwych flag.
Niezmienny audyt: kto/kiedy/co/dlaczego (bilet/incydent link).
Jurysdykcje: Flagi nie mogą obchodzić zakazów regulacyjnych (na przykład obejmują grę w kraju objętym zakazem).
9) Zarządzanie „długotrwałymi” flagami
Każda flaga ma datę TTL/usunięcia.
Po włączeniu 100% - utwórz zadanie usunięcia gałęzi kodu, w przeciwnym razie „dług-flaga” wzrośnie.
Oznaczyć flagi jako „migracja ”/„ jednorazowa”, oddzielając je od stałej „zgody/konfiguracji”.
10) Przykładowa umowa API/SDK
Ocena API (po stronie serwera)
http
POST /v1/flags/evaluate
Headers: X-Tenant: brand_eu
Body: { "keys":["catalog. new_ranker","rgs. killswitch"], "context": { "user_id":"u42", "region":"EE" } }
→ 200
{
"catalog. new_ranker": { "on": true, "variant":"v1", "as_of":"2025-10-31T12:10:02Z" },
"rgs. killswitch": { "on": false, "variant":null, "as_of":"2025-10-31T12:10:02Z" }
}
Klient SDK (кин, fallback)
ts const ff = await sdk. getSnapshot() // bootstrap const on = ff. isOn("catalog. new_ranker", ctx)
const payload = ff. payload("catalog. new_ranker", "v1")
11) Interakcje z innymi obwodami
Limity stawek/kwoty: flagi mogą zmniejszać RPS/umożliwiać zmniejszanie prędkości na czas trwania incydentu.
Wyłącznik/degradacja: kill-switchi wyłączyć ciężkie ścieżki i włączyć degradację.
Katalog/Personalizacja: Flagi zmieniają wagi/zasady rankingu (za pośrednictwem zdalnego Config).
Migracje bazy danych: flagi stopniowo tłumaczą/piszą na nowy schemat (odczyt-replika → dual-write → write-primary).
12) Playbooks (książki startowe)
1. Incydent po włączeniu 25%
Autocatoff uruchomił → flaga OFF dla wszystkich/segmentu, bilet na dyżur, kolekcja statystyk, RCA.
Tymczasowo włączyć degradację/starą gałąź poprzez flagę migracji.
2. p95 katalog wzrostu
Próg 'p95 _ ms> 200' - autokatopa; fix a snapshot of logs with 'flag _ key = catalog. new_ranker'.
Włącz konfigurację ładunku.
3. Brak jurysdykcji
Flaga zezwolenia omyłkowo otworzyła grę w 'NL' - OFF + audyt post-fact, dodając regułę straży „region odmówić”.
4. Wariancja A/B
Zatrzymaj eksperyment, wykonaj analizę CUPED/stratyfikowaną, ponownie zwiń zaktualizowaną skalą.
13) Badanie
Jednostka: deterministyczna ocena zasad/priorytetów/warunków wstępnych.
Umowa: system bandery (JSON/YAML), walidatory, CI-check przed połączeniem.
Oparte na właściwościach: „odmawiają> zezwalają”, „najbardziej konkretne wygrane”, stabilne bucketing.
Replay-Plays prawdziwe konteksty na nowej konfiguracji.
E2E: skrypty kanaryjskie (step-up/step-down), kontrola autocatoff i audyt zdarzeń.
Chaos: Klif strumieniowy, spuścizna migawki, ogromna aktualizacja flagi.
14) Typowe błędy
Tajna logika w flagach klienta (wycieki/spoofing).
Brak TTL → „cmentarz” flag w kodzie.
„Uniwersalne” flagi bez → segmentacja nie może zlokalizować problemu.
Brak barier/autokatofonów - incydenty ręczne.
Niezgodne zależności między flagami → pętle/poza synchronizacją.
Ocena flag w każdym zapytaniu bez pamięci podręcznej → kolce opóźnienia.
Brak audytu/zmiany okna - ryzyko zgodności.
15) Lista kontrolna przedsprzedaży
- Flaga utworzona z wymogiem typu, właściciela, opisu, TTL i biletu.
- Zdefiniowane zasady ukierunkowania; „zaprzeczać” w przypadku niechcianych regionów/ról.
- Lepkie kubełkowanie jest deterministyczne; Identyfikator jest stabilny.
- Wstępne wymagania i flagi zdrowotne gotowe; domyślnie bezpieczne.
- Deski rozdzielcze i wpisy na p95/p99, error_rate, poręcze biznesowe.
- Skonfigurowany autokatoff; próg zatrzymania rolki i warunki wsteczne.
- Plan kanaryjski - wartości procentowe/kamienie milowe/zmiana okna/właściciele
- Konfiguracje są zatwierdzone w CI; migawka rozmieszczona w klastrach/regionach.
- Dokumentacja wsparcia/produktu; odtwarzacze incydentów.
- Plan usunięcia gałęzi kodu i samej flagi po 100%.
16) Przykład flagi „migracja” (DB/indeks)
yaml flag:
key: "search. use_index_v2"
type: "migration"
description: "Switching reads to index v2"
prerequisites:
- key: "search. index_v2_built"
must_be: "on"
rules:
- when: { tenant_id: ["brand_eu"], user_pct: 5 } then: "on"
- when: { tenant_id: ["brand_eu"], user_pct: 25 } then: "on"
safeguards:
auto_rollback_on:
search_p95_ms: ">180"
error_rate: ">1%"
ttl: "2026-02-01"
Wnioski
Flagi funkcji są nie tylko „włączone/wyłączone”, ale dyscyplina zarządzania ryzykiem zmian. Jasne typy flagi, deterministyczne ukierunkowanie, progresywne wyświetlacze z barierkami, autokatowanie, plan audytu i usuwania sprawiają, że wydania są przewidywalne, a incydenty zwięzłe i kontrolowane. Budować flagi w architekturze jako pierwszej klasy obywateli - i można dostarczyć wartość częściej, bezpieczniej i bardziej znacząco.