Implementering af feature flags for mere sikre deployments

deploymentfeature-flagsrisk-managementtooling

Vores deploymentproces var alt-eller-intet. Nye funktioner gik live for alle brugere med det samme ved deployment, hvilket gjorde rollbacks forstyrrende og begrænsede vores mulighed for at teste i produktion.

Implementere et feature flag-system med LaunchDarkly til gradvise rollouts og øjeblikkelige kill switches

Bygge et eget feature flag-system

Fordele
  • Fuld kontrol over implementeringen
  • Ingen ekstern afhængighed
  • Ingen licensomkostninger pr. bruger
Ulemper
  • Betydelig udviklingsindsats
  • Targeting, analytics og UI skal bygges selv
  • Vedligeholdelsesbyrde for teamet

Bruge LaunchDarkly

Fordele
  • Afprøvet i stor skala
  • Righoldige targeting-muligheder
  • Indbygget analytics og eksperimentfunktioner
  • God SDK-understøttelse
Ulemper
  • Månedlig omkostning (~500 USD/måned på vores skala)
  • Ekstern afhængighed
  • Data forlader vores infrastruktur

Bruge miljøvariabler

Fordele
  • Enkel at implementere
  • Ingen eksterne afhængigheder
Ulemper
  • Kræver ny deployment for at ændre
  • Ingen mulighed for gradvis udrulning
  • Ingen brugertargeting

Omkostningen ved LaunchDarkly er berettiget af den sparede udviklingstid og den reducerede risiko ved gradvise rollouts. At bygge et tilsvarende system internt ville tage måneder og kræve løbende vedligeholdelse. Muligheden for øjeblikkeligt at deaktivere problematiske funktioner uden ny deployment er uvurderlig.

Problemet

Vores deployment-angst var høj:

  • Hver deployment var en potentiel hændelse
  • Rollbacks krævede en fuld ny deployment (5-10 minutter)
  • Ingen måde at teste funktioner med en delmængde af brugere på
  • Produktteamet kunne ikke køre A/B-tests

Feature flag-strategi

Vi opstillede mønstre for brug af flags:

Release flags: Midlertidige flags til nye funktioner

if (flags.isEnabled('new-checkout-flow', user)) {
  return newCheckoutFlow();
}
return legacyCheckoutFlow();

Ops flags: Permanente flags til driftskontrol

if (flags.isEnabled('enable-cache', { service: 'api' })) {
  return cachedResponse();
}

Experiment flags: Til A/B-testning

const variant = flags.getVariant('pricing-test', user);
return pricingPages[variant];

Rollout-proces

Nye funktioner følger nu denne proces:

  1. Deploy med flaget deaktiveret (0 %)
  2. Aktiver for interne brugere (dogfooding)
  3. Aktiver for 1 % af brugerne, overvåg
  4. Gradvis forøgelse: 5 % → 25 % → 50 % → 100 %
  5. Fjern flaget, når funktionen er stabil

Resultater

  • Deploymentfrekvens: 3x stigning (mindre frygt)
  • Genoprettelsestid ved hændelser: 90 % reduktion (øjeblikkelig kill switch)
  • A/B-tests kørt: 12 i første kvartal (tidligere 0)
  • Udviklertillid: markant forbedret

De 500 USD/måned har mange gange betalt sig selv tilbage i form af reduceret hændelsespåvirkning og hurtigere iteration.

Erfaringer

  • Flag-hygiejne er vigtig: Vi planlægger oprydning af flags for at undgå teknisk gæld
  • Standard er slukket: Nye flags bør være deaktiveret som standard
  • Dokumentér formålet med flaget: Hvert flag skal have en ejer og en udløbsdato