Metode & udrulning
Hvis I søger efter feature flags i Next.js eller udrulning uden nedetid, står I typisk ét sted: noget skal i produktion, og I tør ikke vise det til alle. Nogen foreslår LaunchDarkly. Nogen sætter NEXT_PUBLIC_NEW_CHECKOUT=true og kalder det et flag. Nogen merger bag en branch, der aldrig bliver merged, fordi 'vi venter på go-live'.
CI/CD-posten handler om preview-URL'en før merge. Den her handler om det, der sker efter merge — når koden er i produktion, og I stadig vil beslutte hvem der ser den. Et flag er ikke et produkt. Det er en runtime-læsning med en ejer og en dødsdato. Uden de to ting har I et indstillingspanel, I aldrig rydder op i.
TL;DR
De vigtigste pointer
- Et flag er en beslutning I kan ændre uden at bygge om. Kræver det en rebuild, er det konfiguration — ikke et flag.
- Preview-deploys svarer på 'må det her merges?'. Flags svarer på 'må den her lejer se det nu?'.
- Et lille team dør af flag-kirkegårde, ikke af at mangle en enterprise-platform.
- Start med boolean og en kill-switch. Targeting og procenter kommer, når I har en sætning om hvem der slår fra.
- I Next.js er den typiske løgn et NEXT_PUBLIC_-flag, der allerede sidder i bundlen, før I 'slår det fra'.
- Hvert flag har en ejer og en slet-dato. Ellers er det blevet produktet.
Hvorfor det her overhovedet er vigtigt
Udrulning uden nedetid er ikke et load-balancer-trick. Det er at I kan sende kode, der er mørk for de fleste, og tænde den når I tør — eller slukke den når den brænder. Uden den ventil merger I om natten, hotfix'er i panik, eller lader en feature rådne på en branch, fordi 'vi ikke kan rulle delvist ud'.
Små teams køber den forkerte medicin. De ser et slide med procentuel udrulning, multivariate tests og 'governance', og tegner et platform-projekt oven på et checkout, der bare skulle kunne slås fra. Eller de gør det modsatte: de har ingen ventil, så hver release er et spring. Begge dele koster uger. Den ene i teater. Den anden i rollback.
Det er også et produktspørgsmål, ikke kun et DevOps-spørgsmål. Et flag, der lever i et år, er en skjult indstilling. To sandheder i koden. To veje i QA. To måder en kunde kan ramme en fejl på. Preview-deploys fanger det, I kan se før merge. De fanger ikke det flag, I glemte at slette efter go-live.
Vi skriver det, fordi 'feature flags' er blevet et køb, I tager før I har en sætning om hvad der slås til. Et ærligt setup er kedeligt: en boolean, et sted I kan læse den i requesten, en person der ejer den, og en dato hvor koden kun har én vej. Uden den sætning har I et dashboard. I har ikke udrulning, I kan forsvare.
Hvad et feature flag faktisk er — og hvad det ikke er
Et feature flag er en værdi, runtime læser, mens requesten kører. Koden er allerede ude. Beslutningen er ikke. Det er forskellen på at deploye og at slå til. Hvis I skal bygge image om, røre Vercel-env og vente på en ny deploy, har I en konfiguration. Den kan være rigtig — en kill-switch I sjældent rører. Den er ikke et flag I kan bruge midt i en hændelse.
Derfor er NEXT_PUBLIC_ENABLE_BILLING=true næsten altid en løgn, når nogen siger flag. NEXT_PUBLIC_ lander i browser-bundlen. Klienten har allerede svaret, før jeres 'off' findes. En middleware, der læser en server-hemmelighed eller en række i jeres database, kan stadig sige nej. Et client-bundle kan ikke tage et nej tilbage, I sendte med for to deploys siden.
Et flag er heller ikke et settings-produkt. 'Hver lejer kan selv slå mørkt tema, nyt dashboard og beta-faktura til' er feature-toggle som forretning. Det kræver UI, audit, support. Det er fint, når det er produktet. Det er gift, når I startede med 'bare så vi kan rulle stille ud' og endte med et internt kontrolpanel, ingen tør røre.
Og det er ikke en erstatning for preview. En PR uden URL er stadig et review i blindo. Flaget hjælper jer ikke med at se layoutet før merge. Det hjælper jer med at have koden ude, uden at alle kunder står på den nye sti. Hvis I kun har det ene, har I kun halvdelen af udrulningen.
Det der typisk går galt i et lille team
Den første fejl er at købe platformen, før I har én boolean, I faktisk slår til og fra. I får SDK, audit-log og 'environments', og så bruger I ét flag til checkout. Tre måneder senere er SDK'et den eneste grund til at flaget stadig findes, og ingen husker API-nøglen. I betaler for governance, I ikke læser.
Den anden fejl er env-var som teater. I skifter en værdi, trigger et redeploy, og kalder det 'udrulning uden nedetid'. Det er en langsom kill-switch. Den er bedre end ingenting, hvis I kun har én knap, I rører ved en hændelse. Den er ubrugelig, hvis I vil tænde for én lejer i eftermiddag uden at bygge om.
Den tredje fejl er targeting som første feature. 'Ti procent af sessionerne, undtagen staff, plus det her workspace'. Nu har I et regelsprog. Nu kan to flags interagere. Nu kan en kunde se A på desktop og B på telefonen, fordi cookien ikke fulgte med. Targeting er rigtigt, når I har et spørgsmål targeting svarer på. Det er forkert som standard på et MVP.
Den fjerde fejl er at lade flaget blive den måde, I gemmer uenigheder. Produkt vil have det ude. Support vil ikke. I merger og lader flaget stå på off. Et halvt år senere tør ingen slette koden, fordi 'den måske skal bruges'. Det er ikke udrulning. Det er en uenighed, I har skubbet ind i runtime.
Preview-deploy vs. feature flag — to forskellige ventiler
Preview-deploy
Svaret før merge: kan vi se det, og tør vi tage det ind?
- En URL pr. pull request, tæt på produktion
- Fanger layout, copy og de fejl, diffen skjuler
- Stakeholders kan sige ja uden at køre lokalt
- Når I merger, er koden ude for alle — medmindre I også har et flag
Feature flag
Svaret efter merge: hvem ser det, og kan vi slukke nu?
- Koden er i produktion; synligheden er det ikke
- En kill-switch I kan slå midt i en hændelse
- Én lejer, ét workspace, eller 'kun os'
- Kræver en slet-dato, ellers bliver det en anden kodebase
Sådan starter et lille team — uden at købe et kontroltårn
Uden den her rækkefølge får I enten teater eller slet ingen ventil.
- 01
Skriv hvad flaget slår til — i én sætning
Ikke 'det nye dashboard'. 'Checkout-v2 for interne brugere, så vi kan tage imod en ordre uden at røre den gamle kurv'. Hvis I ikke kan sige det, er I ikke klar til et flag. I er klar til en branch eller et nej.
- 02
Vælg én boolean, læst på serveren
En række i jeres database, et edge-config I faktisk forstår, eller et lille Unleash/Flagsmith I selv hoster. Læs den i den request, der beslutter. Ikke i en client-bundle. Ikke i en NEXT_PUBLIC_, I håber at kunne tage tilbage.
- 03
Giv den en ejer og en slet-dato
Ejer er et navn, ikke 'teamet'. Datoen er den dag koden kun har én gren — flaget væk, den gamle sti væk. Sæt datoen når I opretter. Flyt den bevidst. Lad den ikke udløbe i stilhed.
- 04
Øv sluk, før I øver tænd
Det farlige er ikke at tænde. Det er at I aldrig har slukket midt i noget. Tag en eftermiddag: tænd for jer selv, sluk, tjek at den gamle sti stadig virker. Hvis sluk kræver et deploy, har I ikke en hændelses-ventil.
- 05
Sig nej til det andet flag, indtil det første er dødt
To levende flags er begyndelsen på et matrix-problem. Et lille team kan bære én udrulningsventil ad gangen. Har I brug for tre, har I brug for en oprydningsuge — ikke et nyt SDK.
“Udrulning uden nedetid er ikke et platform-køb. Det er at I kan slukke det, I lige har tændt — uden at bygge om.”
Next.js — samme pligt, særlige steder I snyder jer selv
App Router gør det nemt at tro, at 'det kører på serveren'. En Server Component kan læse et flag rigtigt. En Client Component, der får flaget som en prop I cached for aggressivt, eller som selv henter et NEXT_PUBLIC_, kan vise den forkerte verden i minutter. Cache er en del af flaget. Hvis I ikke kan sige, hvor længe et 'off' må være forkert, har I ikke en kill-switch. I har et håb.
Middleware er et ærligt sted at gate'e en hel sti — /ny-kasse kun når flaget er på. Det er også et sted, I kan gøre requesten langsom, eller cache'e beslutningen så hårdt, at sluk ikke slår igennem. Hold flag-læsningen kort. Hold den tæt på det, I faktisk vil skjule. Gate ikke hele sitet fordi én flow skal kunne slukkes.
Vercel Flags, edge config og de sædvanlige SaaS-SDK'er kan være rigtige, når I har flere miljøer, flere teams og et behov for at slå til uden et deploy. De er forkerte som første commit på et MVP, hvor én person kan opdatere en række og refreshe. Køb pipen, når læsningen er blevet et produkt. Køb den ikke, fordi et blogindlæg sagde, at feature flags er 'moderne'.
Hvis I overvejer at skifte host eller framework 'for at få flags', så vær ærlige: I skifter sted, beslutningen kan sidde. Et Next.js-site med det samme env-teater er ikke en ny ventil. Skift stak hvis I også har andre grunde. Skift ikke fordi et slide sagde, at edge gør udrulning usynlig. Udrulning er hvem der ser koden. Ikke hvor den compiles.
Hvad I typisk bør gøre i den situation, I står i
Venstre er det, I typisk siger. Højre er det næste skridt, vi typisk anbefaler.
Situation
Vi tør ikke merge, fordi det skal kunne slås fra i produktion
Næste skridt
Merge bag én server-boolean med ejer og slet-dato. Preview er allerede ja/nej på URL'en — flaget er ja/nej efter merge
Situation
Vi har sat et NEXT_PUBLIC_-flag og kalder det udrulning uden nedetid
Næste skridt
Flyt læsningen til serveren. Det, browseren allerede har fået, kan I ikke tage tilbage med et env-skift
Situation
Vi vil rulle ud til ti procent og A/B'e overskriften samtidig
Næste skridt
I vil have to ting. Først en kill-switch. Targeting og eksperimenter er et andet produkt — og et andet rod, hvis I blander dem
Situation
Vi kigger på LaunchDarkly, før vi har slået ét flag fra i en hændelse
Næste skridt
Øv sluk på én boolean I ejer. Køb platformen, når flere teams skal slå til uden at røre jeres database
Situation
Vi har syv flags, og ingen husker hvad der er sandt i produktion
Næste skridt
Oprydningsuge. Slet eller merge hver gren. Ingen nye flags før listen er kort nok til at stå på ét kort
Tjekliste før I kalder det feature flags
Hvis I mangler flere af punkterne, er sætningen et slide — ikke en ventil.
- Læsningen sker i requesten, ikke i et client-bundle I allerede har sendt
- Sluk virker uden et nyt image — I har prøvet det, ikke kun tænd
- Hvert flag har et navn, en ejer og en slet-dato I tør rykke offentligt
- Preview-deploys findes stadig; flaget erstatter dem ikke
- I har højst få levende flags, og I kan sige hvad produktion viser uden at åbne et dashboard
- Ingen 'settings for hver lejer' gemt som udrulningsflags
Spørgsmål vi får igen og igen
Har et lille team overhovedet brug for feature flags?
I har brug for en ventil, når koden skal ude, før I tør vise den til alle — en lejer, et internt workspace, en kill-switch midt i en hændelse. I har ikke brug for en flag-platform, fordi et slide sagde 'modern delivery'. Mange små teams klarer sig med preview-deploys og et sjældent env-skift. Tag flaget, når 'sluk nu' er et rigtigt krav. Tag det ikke, fordi I gerne vil lyde som et platform-team.
Er en env-var i Vercel ikke nok?
Den er nok som en sjælden kill-switch, hvis I accepterer et redeploy. Den er ikke nok, hvis I vil tænde for én kunde i eftermiddag, eller slukke midt i en fejl uden at vente på build. Og en NEXT_PUBLIC_-var er næsten aldrig nok: den sidder i bundlen. Sig 'konfiguration vi rører ved hændelser'. Sig ikke feature flag, medmindre runtime kan læse et nej uden at I bygger om.
Hvornår er LaunchDarkly eller Unleash det rigtige?
Når flere mennesker skal slå til uden at røre jeres database, når I har flere miljøer der skal spejle hinanden, eller når audit er et rigtigt krav — ikke et nice-to-have på et slide. Unleash I selv hoster kan være den rigtige mellemting. En fuld SaaS-platform er rigtig, når flag-læsning er blevet drift for flere teams. Den er forkert som første afhængighed på et checkout, én udvikler ejer.
Kan vi bruge flags til A/B-test og targeting med det samme?
I kan. I bør ikke, før I har én boolean I tør slukke. A/B er et eksperiment med statistik og en udløbsdato. Targeting er et regelsprog. Feature-udrulning er en ventil. Bland dem, og I kan ikke sige om en fejl sad i varianten, i reglen eller i produktet. Ét job pr. flag. Ét flag pr. udrulning. Eksperimenter i et værktøj, I kan slukke uden at røre udrulningen.
Hvor længe må et flag leve?
Så kort at I kan huske den gamle gren. En udrulning over dage eller få uger er et flag. Et halvt år er en skjult indstilling. Hvis datoen rykker tredje gang, er det ikke en udrulning. Det er uenighed eller et settings-produkt. Merge grenen, slet flaget, eller indrøm at I har bygget to produkter og skal designe det ærligt — med UI, support og en rigtig indstilling, ikke et runtime-hack.
Hvis I kun tør merge, når alle skal se det med det samme
Lad os skille preview, ventil og platform ad.
En boolean I kan slukke slår et dashboard, I køber før I har øvet et nej.
