Vad är en feature flag? En praktisk guide för utvecklarlag

Summary

Feature flags låter dig distribuera kod utan att distribuera funktioner. Det är ett enkelt koncept: ett villkor vars värde kommer från konfiguration i stället för hårdkodning. Men när du har hundratals flaggor blir det fort teknisk skuld. Den här guiden täcker praktiska strategier för att hantera det.

Ingenjoersskrivbord med en rad fysiska kopplingsomkopplare bredvid en laptop

En feature flag är ett villkor i koden som avgör vid runtime om en viss funktion är på eller av, utan att behöva distribuera om. Det är själva idén. Vad är en feature flag i praktiken? Ett if-statement vars svar kommer från konfiguration, en databasrad eller en flaggtjänst i stället för att vara hårdkodad.

Konceptet är enkelt. Att leva med 200 av dem i ett repo är inte enkelt, och det andra är det denna guide egentligen handlar om.

Hur ser en feature flag ut i kod?

Här är den minsta användbara versionen:

if (flags.isEnabled("new-checkout", { userId })) {
  return renderNewCheckout();
}
return renderOldCheckout();

Båda kodvägarna levereras i samma bygge. Flaggvärdet finns någonstans du kan ändra utan att distribuera om: en miljövariabel, en JSON-fil, en tabell eller en värdtjänst. Ändra värdet, och beteendet ändras vid nästa evaluering.

Den separationen är poängen. Distribution är att sätta kod på servrar. Release är att låta användare se det. Flaggor delar dessa två händelser, så merge till main betyder inte längre "alla får detta nu".

Hand flipping a single toggle switch with a green indicator light

Varför använder lag feature flags överhuvudtaget?

Tre anledningar dyker upp om och om igen i riktiga lag med 5 till 50 utvecklare.

Ingen av dessa kräver en leverantör. En flagga kan vara ett booleskt värde i en konfigurationstabell. Hoppa över plattformen tills du behöver procentuella utrullningar, granskningsloggar eller icke-ingenjörer som växlar saker.

Vilka är de fyra typerna av feature flags?

Pete Hodgsons flitigt citerade artikel om feature toggles på Martin Fowlers webbplats sorterar flaggor efter hur länge de lever och hur ofta beslutet ändras. Kategorierna är fortfarande den klaraste mentala modellen.

Livslängdkolumnen spelar mest roll. En releaseflagga som överlevér sin release är en bugg du inte har hittat än. En permissionsflagga som raderas i en rensningssprint är ett driftavbrott du inte har haft än.

Namn och etikett typen när du skapar flaggan. Sex månader senare kommer ingen ihåg vilken kategori "new-nav-v2" var.

Team planning grid of sticky notes grouped by category

Hur rullar du ut en flagga utan att skada användare?

Den tråkiga sekvensen fungerar bäst.

  1. Leverera koden med flaggan av. Verifiera att ingenting ändrades.

  2. Aktivera för ditt eget lag i produktion. Använd det i en dag.

  3. Aktivera för 1% till 5% av användarna, klibbig per användar-ID så att ingen växlar mellan varianter under sessionen.

  4. Bevaka felfrekvens, latens och ett affärsmått. Bestäm tröskeln innan du börjar, inte medan du stirrar på en instrumentpanel.

  5. Rulla till 100%, vänta en bestämd period, ta sedan bort flaggan.

Steg fem är det lag hoppar över. Vi kommer till varför det kostar mer än du tror.

En praktisk anmärkning om evaluering: gör flaggläsningar billiga och felsäkra. Om flaggtjänsten är nere behöver din kod en standard. Välj standard per flagga, avsiktligt. En killswitch bör misslyckas till "säker", medan en ny funktion bör misslyckas till "av".

Varför blir feature flags teknisk skuld?

Varje flagga är en förgrening i din kod. Två flaggor skapar fyra möjliga vägar, tio flaggor skapar 1 024, och du testade säkert en handfull av dem. GrowthBooks guide till flaggskuld citerar forskning som visar att cirka 75% av toggle-komponenter fortfarande fanns i kodbasor upp till 49 veckor efter att de infördes, även om de flesta utvecklare sa att de planerade ta bort dem.

Hodgson säger det väl i samma Fowler-artikel: erfarna lag behandlar toggles som inventering med en bärkostnad, och arbetar för att hålla det lagret lågt.

Skräckhistorian är Knight Capital 2012. En pensionerad funktions flagga återanvändes för nytt beteende medan gammal kod fortfarande satt på en server. Det missförhållandet bidrog till ungefär 460 miljoner dollar i förluster på under en timme. Din gamla flagga gör förmodligen inte det. Den gör något tystare: en omstrukturering som bryter en branch som ingen visste fanns, eller en nyanställd som tillbringar en eftermiddag att ta reda på vilka av två kassakontrollvägar som är verklig.

Dusty shelf of forgotten boxes and old switches

Hur hittar du alla flaggor i en befintlig kodbas?

Det här är frågan leverantördokumentationen hoppar över, och det är där de flesta lag fastnar. Flagginstrumentpanelen säger dig vad som är konfigurerat. Den säger dig inte var varje flagga läses i koden eller om kodvägen bakom en "av" flagga fortfarande är nåbar.

Börja med det billiga tillvägagångssättet:

# varje litteral flaggnyckel läst via din wrapper
rg -n 'isEnabled\("' src/ | sort

# flaggor definierade men aldrig refererade
comm -23 <(jq -r 'keys[]' flags.json | sort) \
         <(rg -o 'isEnabled\("([^"]+)"' -r '$1' src/ | sort -u)

Det bryter ner fort. Flaggnycklar byggda från strängsammanfogning dyker inte upp i grep. Flaggor som skickas genom hjälpfunktioner döljer sina anropsplatser. Monorepos och multi-repo-inställningar multiplicerar problemet, eftersom samma nyckel kan läsas av tre tjänster.

Det är där kodläsning med verktyg hjälper. Kodsökverktyg som förstår ditt repo kan svara "var är new-checkout utvärderad, och vad beror på resultatet?" i en fråga i stället för en eftermiddag grep. Cursor och GitHub Copilot hanterar det rimligt inom ett repo. Över flera repo behöver du ett index som omfattar alla, vilket är fallet vi byggde codebasechat för.

Hur ser en vettig flaggrensningsprocess ut?

Behandla borttagning som en del av arbetet, inte en syssla för senare.

Statisk analys hjälper här också. Ett verktyg som CodeScene kan visa vilka filer som har det mest trassligt villkoret, vilket är vanligtvis där gamla flaggor samlas. SonarQube flaggar onåbar och död kod efter att du tar bort en kontroll.

Hur testar du kod som sitter bakom en flagga?

Testning är den delen ingen budgeterar för. Med två vägar per flagga behöver din testsvit täcka båda, åtminstone för flaggor som skyddar riskabelt beteende.

Håll det praktiskt. Testa på- och av-tillstånden för varje releaseflagga i enhetstester genom att injicera flaggvärdet i stället för att läsa en live-tjänst. Kör en end-to-end-svit mot standardproduktionskonfigurationen, eftersom det är vad användare får idag. Kör sedan ett andra pass med flaggan på för funktionen du är på väg att frigöra.

Försök inte testa varje kombination. Med tio flaggor kan du inte. I stället håll flaggor oberoende: en flagga som bara ändrar beteende när en annan flagga också är på är en designlukt, och det är det första att reda ut.

Vad får nya ingenjörer fel med flaggor?

Nyutexaminerade tenderar att göra samma tre misstag, och varje är billigt att förhindra vid granskning.

De första två veckorna av en nyanställd är exakt när de stöter på gamla flaggor utan ägare. Ett kort flaggregister, med en typ, en ägare och ett borttagningsdatum för varje post, sparar flera timmar av att fråga omkring.

När bör du hoppa över feature flags?

Flaggor är inte gratis, så hoppa över dem när:

Och använd dem utan tvekan när en ändring är riskabel, användarvänd och svår att vända genom omfördelning. Betalningsflöden, autändringar och vad som helst med en datamigrering bakom sig kvalificeras.

Vad skulle vi faktiskt göra i ett lag på tio

Börja med ett booleskt värde i konfiguration och en wrapper-funktion, så varje flaggläsning går genom ett ställe. Det enda strypunkten gör flagglistan greppbar, granskningsmässig och enkel att migrera till en värdtjänst senare.

Märkta varje flagga efter typ, ge den en ägare och arkivera borttagningsbiljetten på dag ett. Granska listan varje månad i tio minuter. Ta bort flaggor som har varit på 100% i två veckor.

En feature flag är ett lån. Ta det när det sparar dig en riskabel release, och betala tillbaka det innan räntan dyker upp i din nästa refaktorering. Behandla flaggor som inventering med bärkostnad, inte som en gratis utbredning av versioner.

Frequently asked questions

Vad är huvudskillnaden mellan en feature flag och en miljövariabel?
En feature flag kan ändras i realtid utan ny distribution, medan miljövariabler kräver omstart. Flaggor är utformade för snabba ändringscykler under utveckling och release.
Hur länge bör man behålla en feature flag aktiv?
Det beror på flaggtypen. Release-flaggor bör ta bort inom veckor, experiment-flaggor inom några veckor, ops-flaggor kan vara långlivade, och permission-flaggor kan behållas under månader eller år.
Kan feature flags orsaka säkerhetsproblem?
Ja, gamla flaggor kan dölja säkerhetsluckor. Om en säkerhetskritisk kod ligger bakom en flagga som är av, och att flagga är glömd, kan den skapa sårbarhet. Regelbundna granskningar är viktiga.
Vilken är den enklaste implementationen av feature flags?
En enkel boolean i en konfigurationsfil eller miljövariabel med ett wrapper-funktions som läser värdet. Ingen extern tjänst behövs för att komma igång.
Hur testar man kod bakom feature flags?
Testa både på- och av-tillstånden för varje flagga i enhetstester. Injicera flaggvärden direkt i stället för att läsa från en live-tjänst för reproducerbara tester.
Vad är teknisk skuld när det gäller feature flags?
Glömda eller gamla flaggor som aldrig tas bort. De ökar kodkomplexiteten, multiplicerar testvägar och kan dölja oreferenserad kod som gör refaktorering riskabelt.