Feature Flag to technika programistyczna, w której funkcjonalność aplikacji jest włączana lub wyłączana za pomocą warunkowych przełączników w czasie wykonywania, bez wdrażania nowego kodu. Zamiast tradycyjnego podejścia „zatwierdź — wdróż”, flagi funkcji pozwalają oddzielić moment wdrożenia od momentu włączenia funkcjonalności. Według danych LaunchDarkly (2024), zespoły używające flag funkcji skracają czas wdrażania nowych funkcji o 40%. Flagi funkcji stały się obowiązkowym elementem CI/CD dla nowoczesnych aplikacji mobilnych i webowych.
Najważniejsze
Feature Flag (flaga funkcji, przełącznik funkcji) — to mechanizm umożliwiający zmianę zachowania aplikacji bez zmiany kodu. W najprostszej postaci jest to konstrukcja warunkowa, która sprawdza wartość flagi przed wykonaniem nowej funkcjonalności. Flaga może być przechowywana w pliku konfiguracyjnym, bazie danych lub zewnętrznym serwisie i zmieniana w czasie rzeczywistym. Takie podejście pozwala zespołom zatwierdzać niezakończony kod do głównej gałęzi bez obawy, że trafi on do użytkowników przed zakończeniem prac.
Głównym przeznaczeniem flag funkcji jest rozdzielenie wdrożenia i wydania. Wdrożenie to proces umieszczenia kodu na serwerze lub w sklepie z aplikacjami. Wydanie to moment, w którym funkcjonalność staje się dostępna dla użytkownika. Bez flag funkcji te zdarzenia pokrywają się: kod trafia do produkcji — użytkownicy go widzą. Dzięki flagom funkcji kod może być wdrożony do produkcji tygodnie przed wydaniem, włączony do wewnętrznych testów lub stopniowo udostępniany odbiorcom. Jest to kluczowe dla rozwoju opartego na głównej gałęzi i ciągłego dostarczania.
Rozwaźmy podstawową implementację flagi funkcji w mobilnej aplikacji w Kotlinie. Flaga jest przechowywana w Firebase Remote Config i ładowana przy uruchomieniu aplikacji. W zależności od wartości flagi wyświetlany jest stary lub nowy ekran profilu. Taka implementacja pozwala na wydanie nowej wersji profilu bez publikowania aktualizacji w App Store — wystarczy zmienić wartość w konsoli Firebase.
class ProfileFeature {
private val flags = FeatureFlagProvider()
private val profileFlag = FlagKey("new_profile_enabled")
fun getProfileScreen(): Screen {
return if (flags.isEnabled(profileFlag)) {
NewProfileScreen()
} else {
LegacyProfileScreen()
}
}
}
class FeatureFlagProvider {
fun isEnabled(key: FlagKey): Boolean {
val raw = Firebase.remoteConfig.getString(key.name)
return raw.toBoolean()
}
}
Nie wszystkie flagi funkcji są jednakowe. Martin Fowler w swojej klasyfikacji wyróżnia cztery typy flag, różniących się celem użycia, długością życia i wymaganiami dotyczącymi zarządzania. Prawidłowa klasyfikacja flag pomaga wybrać odpowiednią infrastrukturę i uniknąć typowych problemów.
Release toggles — najpopularniejszy typ flag. Służą do ukrywania niezakończonej funkcjonalności w środowisku produkcyjnym. Programista zatwierdza kod do głównej gałęzi, owinięty flagą, i stopniowo dokończa funkcjonalność. Po zakończeniu i przetestowaniu flaga jest włączana dla wszystkich użytkowników. Cykl życia takiej flagi wynosi od kilku dni do dwóch tygodni. Po pełnym wdrożeniu flaga jest usuwana z kodu. Release toggles są podstawą rozwoju w głównej gałęzi.
Experiment toggles działają w połączeniu z testami A/B. Nie tylko włączają/wyłączają funkcjonalność, ale kierują użytkownika do jednej z grup eksperymentalnych. Takie flagi często obsługują złożone reguły targetowania (według regionu, wersji systemu operacyjnego, subskrypcji) oraz integrację z systemami analitycznymi. Ops toggles są używane do kontroli operacyjnej — na przykład wyłączenia wymagającej funkcji przy wysokim obciążeniu lub tymczasowego wyłączenia problematycznego modułu bez natychmiastowego wdrożenia. Ops toggles muszą być maksymalnie szybkie i niezawodne, ponieważ od nich zależy stabilność usługi.
| Typ | Czas trwania | Dynamika | Cel |
|---|---|---|---|
| Release | Dni-tygodnie | Stały | Ukrywanie niezakończonego kodu |
| Experiment | Dni-miesiące | Dynamiczny | Testy A/B i wdrażanie |
| Ops | Godziny-dni | Dynamiczny | Kontrola operacyjna |
| Permission | Miesiące+ | Statyczny | Różnicowanie dostępu |
Zarządzanie flagami funkcji to odrębna dyscyplina obejmująca przechowywanie, konfigurację, monitorowanie i audyt flag. Bez systemu zarządzania flagi zamieniają się w niekontrolowany dług techniczny, spowalniający rozwój. Rozważmy kluczowe aspekty zarządzania na przykładzie systemu produkcyjnego.
Każda flaga funkcji przechodzi przez cztery etapy: tworzenie, użycie, stabilizację i usunięcie. Na etapie tworzenia określany jest klucz flagi, typ i wartość domyślna. W trakcie użycia zespół monitoruje, kto włączył flagę, dla jakiej grupy odbiorców i w jakim celu. Po stabilizacji (funkcjonalność jest w pełni gotowa i przetestowana) flaga musi zostać usunięta z kodu. Proces usuwania jest automatyzowany poprzez przegląd kodu: CI sprawdza, czy wszystkie flagi włączone dla 100% użytkowników mają zadanie do usunięcia.
Flagi funkcji powinny być przechowywane centralnie, a nie rozproszone po plikach konfiguracyjnych każdej usługi. Idealnie — wydzielona usługa z interfejsem użytkownika (LaunchDarkly, Unleash). Minimalnie akceptowalna opcja — konfiguracja JSON w repozytorium z przeglądem kodu przy zmianach. Baza danych do przechowywania flag jest mniej preferowana, ponieważ wymaga osobnego interfejsu do zarządzania. Każda flaga powinna mieć właściciela (zespół lub konkretnego programistę), opis i okres ważności. Regularny audyt nieaktualnych flag to obowiązkowa praktyka, automatyzowana poprzez zadanie CI sprawdzające flagi bez zmian dłużej niż N dni.
Rynek narzędzi do zarządzania flagami funkcji obejmuje zarówno platformy komercyjne z pełnym cyklem zarządzania, jak i rozwiązania open-source do samodzielnego wdrożenia. Wybór narzędzia zależy od skali zespołu, wymagań dotyczących opóźnienia i zgodności.
LaunchDarkly — lider rynku z SDK dla wszystkich popularnych języków i platform (iOS, Android, Web, Backend). Obsługuje wiele środowisk, targetowanie oparte na regułach, eksperymenty A/B i automatyczne usuwanie flag. Split — alternatywa skupiająca się na funkcjach korporacyjnych: kontrola dostępu oparta na rolach, dzienniki audytu i zgodność (SOC2, HIPAA). ConfigCat — lżejsze i bardziej przystępne rozwiązanie, odpowiednie dla małych zespołów. Wszystkie platformy udostępniają SDK z buforowaniem wartości i minimalnym wpływem na opóźnienie aplikacji.
Unleash — najpopularniejsze rozwiązanie open-source z interfejsem użytkownika, API i SDK dla wszystkich głównych platform. Obsługuje strategie aktywacji, niestandardowe konteksty i integrację z Prometheus do monitorowania. Flagsmith — alternatywa z wbudowanym testowaniem A/B i zarządzaniem środowiskami. Rozwiązania open-source wymagają wdrożenia i utrzymania infrastruktury, ale dają pełną kontrolę nad danymi i nie mają ograniczeń licencyjnych. Dla aplikacji mobilnych oba rozwiązania udostępniają natywne SDK z buforowaniem offline wartości flag.
Flagi funkcji to potężne narzędzie, ale bez dyscypliny tworzą dług techniczny i komplikują kod. Martin Fowler i inżynierowie LaunchDarkly sformułowali zestaw praktyk, które pomagają wyciągnąć maksimum korzyści z flag funkcji bez negatywnych konsekwencji. Rozważmy kluczowe zalecenia dla systemów produkcyjnych.
Każda flaga funkcji, która nie została usunięta po zakończeniu wdrażania, staje się długiem technicznym. Badanie LaunchDarkly (2024) wykazało, że średnio 30–40% flag pozostaje w kodzie po tym, jak przestają być potrzebne. Rozwiązanie: wdrożyć zasadę „jedna flaga — jedno zadanie”. Przy tworzeniu flagi w systemie śledzenia zadań zakładane jest zadanie jej usunięcia z terminem. CI sprawdza, czy nie ma flag włączonych na 100% dłużej niż 30 dni. Przegląd kodu powinien sprawdzać nie tylko dodawanie, ale także usuwanie flag.
Flagi funkcji tworzą złożoność kombinatoryczną dla testowania: każda flaga podwaja liczbę możliwych stanów aplikacji. Do zarządzania tą złożonością używane są testy macierzowe, sprawdzające wszystkie kombinacje flag, oraz testy integracyjne przełączania flag. W pipeline CI dodawany jest krok, który uruchamia testy z różnymi kombinacjami wartości flag. Dla krytycznych flag (ops toggles) obowiązkowe są testy obciążeniowe sprawdzające, czy przełączenie flagi nie powoduje skoków opóźnienia lub błędów.
class FeatureFlagService:
def __init__(self, storage):
self.storage = storage
def is_enabled(self, flag_key, user_context):
flag = self.storage.get(flag_key)
if not flag:
return False
for rule in flag["rules"]:
if self._match_rule(rule, user_context):
return rule["value"]
return flag["default"]
def _match_rule(self, rule, context):
return (
rule["percentage"] > self._hash(context.user_id)
)
Często zadawane pytania
Terminy są często używane zamiennie, ale jest różnica: feature flag zwykle oznacza bardziej dojrzały system z centralnym zarządzaniem, interfejsem użytkownika i SDK, natomiast feature toggle to prosty binarny przełącznik w kodzie. Martin Fowler używa terminu feature toggle jako ogólnego określenia, ale w branży feature flag często kojarzy się z komercyjnymi platformami (LaunchDarkly, Split).
Wpływ na wydajność jest minimalny przy prawidłowej implementacji. Najlepsze praktyki: buforowanie wartości flag w pamięci z TTL 30–60 sekund, unikanie synchronicznych wywołań HTTP przy sprawdzaniu flagi, używanie SDK z lokalnym buforem i synchronizacją w tle. Według LaunchDarkly, opóźnienie p99 ich SDK wynosi mniej niż 5 ms, co jest nieznaczne dla większości aplikacji.
Flagi funkcji nie są zalecane do zmiany logiki biznesowej w krytycznych operacjach finansowych, gdzie ważne jest dokładne określenie, który kod jest wykonywany. Należy także unikać flag dla funkcji bezpieczeństwa (autoryzacja, szyfrowanie) — wyłączenie takiej flagi tworzy lukę. W przypadku zmian infrastrukturalnych (zmiana bazy danych, migracja do nowej architektury) flagi funkcji są przydatne, ale wymagają szczególnie starannego testowania.
Główne podejście to testowanie macierzowe: uruchamianie testów ze wszystkimi kombinacjami flag. Dla CI/CD może to być zbyt kosztowne (2^n kombinacji), dlatego w praktyce testuje się wszystkie flagi osobno w obu stanach (włączona/wyłączona), a dla kombinacji — tylko krytyczne. Testy jednostkowe powinny wyśmiewać wartość flagi. Testy integracyjne sprawdzają konkretne scenariusze ze znanymi wartościami flag. Testy E2E pokrywają najbardziej prawdopodobne kombinacje.
Proces usuwania: 1) upewnij się, że flaga jest włączona w 100% dla wszystkich użytkowników i nie jest używana w trybie eksperymentu; 2) usuń wszystkie warunkowe sprawdzenia flagi z kodu, pozostawiając tylko „nową” gałąź; 3) usuń definicję flagi z systemu zarządzania; 4) zaktualizuj testy, usuwając wyśmiewanie dla usuniętej flagi. Zaleca się automatyzację tego procesu przez CI: flagi bez zmian dłużej niż N dni są oznaczane jako nieaktualne i wymagają potwierdzenia usunięcia.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również