Blue-green vs canary-implementaties: veiligere API- en databasewijzigingen
Blue-green vs canary-implementaties uitgelegd voor API- en databasewijzigingen, met praktische stappen om downtime-risico te verkleinen tijdens schema-migraties en trage mobiele client-updates.

Waarom deployments riskant worden bij schema-wijzigingen en trage mobiele updates
Een deploy kan in tests perfect lijken en toch falen zodra het echt verkeer bereikt. De gebruikelijke reden is dat niet alleen je code verandert. Ook je API-contract en je databaseschema veranderen, en die wijzigen zelden in hetzelfde tempo.
Dingen breken wanneer verschillende onderdelen van het systeem het oneens zijn over wat "correct" betekent. Een nieuwe backend verwacht een kolom die nog niet bestaat. Een oudere backend schrijft data in een vorm die de nieuwe code niet meer begrijpt. Zelfs kleine wijzigingen zoals het hernoemen van een veld, strengere validatie of het veranderen van een enum-waarde kunnen productieproblemen veroorzaken.
Mobiele apps verhogen de inzet omdat oude versies blijven bestaan. Sommige gebruikers updaten binnen minuten, andere pas na weken. Dat betekent dat je backend meerdere generaties clients tegelijk moet bedienen. Als je een API-uitrol maakt die alleen met de nieuwste app werkt, kun je checkout, onboarding of achtergrondsync voor een groep gebruikers kapotmaken zonder het direct te merken.
"Downtime risico" is niet alleen dat de site offline is. In echte systemen toont het zich vaak als gedeeltelijke fouten:
- een piek in 4xx/5xx fouten op specifieke endpoints terwijl de rest goed lijkt te werken
- aanmeldingen die falen omdat tokens, rollen of gebruikersrecords niet meer overeenkomen
- stille dataproblemen (verkeerde defaults, afgekapt tekst, ontbrekende relaties) die pas dagen later opduiken
- achtergrondjobs die vastlopen en een wachtrij opbouwen die uren duurt om weg te werken
Daarom vergelijken teams blue-green vs canary deployments: je probeert de blast radius te verkleinen wanneer wijzigingen niet perfect compatibel zijn.
Blue-green en canary in gewone taal
Als mensen blue-green vs canary vergelijken, beantwoorden ze meestal één vraag: wil je een grote, gecontroleerde switch, of een kleine, voorzichtige test?
Blue-green: twee volledige versies en een traffic switch
Blue-green betekent dat je twee complete omgevingen tegelijk draait. "Blue" is de huidige versie die gebruikers bedient. "Green" is de nieuwe versie, uitgerold en getest in parallel. Als je klaar bent, schakel je het verkeer van blue naar green.
Deze aanpak is geweldig voor voorspelbaarheid. Je kunt de nieuwe versie valideren met productie-achtige instellingen voordat die echte gebruikers bedient, en vervolgens één schone cutover doen.
Rollback is ook eenvoudig: als er iets misgaat na de switch, routeer je het verkeer terug naar blue. Het is bijna een directe switchback, maar caches, achtergrondjobs en dataveranderingen kunnen herstel alsnog bemoeilijken.
Canary: stuur eerst een klein percentage verkeer
Canary betekent dat de nieuwe versie eerst live gaat voor een klein deel van de gebruikers of verzoeken. Als het gezond lijkt, verhoog je dat percentage stap voor stap totdat het iedereen bedient.
Canary is het beste wanneer je bang bent voor onbekend gedrag onder echt verkeer. Je kunt problemen vroeg vangen, voordat de meeste gebruikers ze voelen.
Rollback werkt door het canary-percentage terug naar nul te brengen (of stoppen met routeren naar de nieuwe versie). Het is meestal snel, maar niet altijd schoon, omdat sommige gebruikers al data of state gecreëerd kunnen hebben die beide versies moeten afhandelen.
Een simpele manier om de trade-offs te onthouden:
- Blue-green geeft de voorkeur aan schone cutovers en snelle switchbacks.
- Canary geeft de voorkeur aan leren van echt verkeer met een beperkt blast radius.
- Geen van beide maakt database-risico automatisch ongedaan. Als schema-wijzigingen niet compatibel zijn, kunnen beide falen.
- Canary hangt af van monitoring omdat je op live signalen beslist.
- Blue-green heeft vaak extra capaciteit nodig omdat je twee volledige stacks draait.
Voorbeeld: als je een API vrijgeeft die soms een nieuw veld terugstuurt, helpt een canary om te zien of oudere clients crashen op onverwachte data. Als de wijziging een kolomnaam verandert die oude code niet kan verwerken, redt blue-green je niet tenzij de schema-wijziging zo is ontworpen dat beide versies worden ondersteund.
Wat maakt database-migraties anders dan code-deploys
Een code-deploy is meestal makkelijk terug te draaien. Als de nieuwe versie zich misdraagt, redeploy je de oude build en dan ben je grotendeels terug waar je was.
Een database-wijziging is anders omdat die de vorm van je data verandert. Zodra rijen herschreven zijn, kolommen verwijderd worden of constraints verscherpt zijn, is teruggaan zelden meteen mogelijk. Zelfs als je applicatiecode terugdraait, kan die de nieuwe schema niet begrijpen.
Daarom heeft schema-migratie downtime risico vaak minder te maken met de deploy-methode en meer met hoe de migratie ontworpen is.
Basisprincipes van online migraties
De veiligste migraties zijn zo ontworpen dat oude en nieuwe appversies tegelijk kunnen draaien. Het patroon is simpel: maak een wijziging die veilig genegeerd kan worden, update de code om het te gebruiken en ruim later op.
Een veelgebruikt expand-then-contract-sequentie ziet er zo uit:
- Additieve wijzigingen eerst: voeg een nullable kolom toe, voeg een nieuwe tabel toe, voeg een index toe op een manier die geen writes blokkeert.
- Dubbel gedrag: schrijf naar zowel oud als nieuw, of lees van nieuw met fallback naar oud.
- Backfill apart: migreer bestaande data in kleine batches.
- Switchover: verplaats het merendeel van het verkeer naar het nieuwe gedrag.
- Destructieve wijzigingen als laatste: verwijder oude kolommen, verwijder oude codepaden, verscherp constraints.
"Big bang" migraties combineren de meest riskante stappen in één release: lange locks, zware backfills en code die ervan uitgaat dat het nieuwe schema overal bestaat.
Waarom trage mobiele updates de lat hoger leggen
Mobiele clients kunnen weken op oude versies blijven. Je backend moet oude requests blijven accepteren en oude responses blijven produceren terwijl de database evolueert.
Als een oudere app een request zonder een nieuw veld stuurt, kan je server dat veld niet plotseling verplicht maken in de database. Je hebt een periode nodig waarin beide gedragingen werken.
Welke strategie vermindert downtime-risico voor schema-migraties
De veiligste keuze hangt minder af van het deploy-instrument en meer van één vraag: kunnen zowel de oude als de nieuwe appversie correct draaien op hetzelfde databaseschema voor een tijdje?
Als het antwoord ja is, is blue-green vaak de optie met de minste downtime. Je kunt de databasewijziging eerst voorbereiden, het verkeer op de oude stack houden en daarna in één cutover naar de nieuwe stack switchen. Als er iets mis lijkt, schakel je snel terug.
Blue-green faalt nog steeds wanneer de nieuwe app het nieuwe schema onmiddellijk vereist. Veelvoorkomende voorbeelden zijn het verwijderen of hernoemen van een kolom die de oude versie nog leest, of het toevoegen van een NOT NULL constraint voordat de app de waarde schrijft. In die gevallen is rollback mogelijk onveilig omdat de database al incompatibel is.
Canary is beter wanneer je gecontroleerd wilt leren. Een klein deel van echt verkeer raakt eerst de nieuwe versie, wat helpt om edge-cases te vinden zoals missende indexes, onverwachte querypatronen of achtergrondjobs die zich anders gedragen onder productiebelasting. Het nadeel is dat je beide versies tegelijk werkend moet houden, wat meestal backward compatible database-wijzigingen vereist.
Een praktische beslisregel
Bij het afwegen van blue-green vs canary voor schema-migratie downtime risico:
- Kies blue-green wanneer je de schema-wijziging additief en compatibel kunt houden en je vooral een snelle, schone switch wilt.
- Kies canary wanneer je niet zeker weet hoe de wijziging zich in productie gedraagt of wanneer je verwacht dat zeldzame data-vormen belangrijk zijn.
- Als de migratie een onmiddellijke brekende wijziging vereist, kies dan niet tussen blue-green en canary. Pas het plan aan naar expand-then-contract.
Hoe "compatibel" er in de praktijk uitziet
Stel dat je een nieuw veld toevoegt aan een orders-tabel. Een veilig pad is: voeg de kolom toe als nullable, deploy de app die hem schrijft, backfill oude rijen en handhaaf later constraints. In die opzet geeft blue-green je een schone cutover en canary geeft je een vroege waarschuwing als een codepad nog van de oude vorm uitgaat.
Hoe trage mobiele updates de keuze beïnvloeden
Webgebruikers verversen de pagina. Mobiele gebruikers doen dat niet.
Op iOS en Android blijven mensen weken of maanden op oude versies. Sommigen updaten pas als de app hen dwingt, en sommige apparaten zijn lange tijd offline. Dat betekent dat je "oude" client je API blijft aanroepen lang nadat je een nieuwe backend hebt uitgebracht. Oudere mobiele clients worden daarmee permanente tests voor backward compatibility.
Dat verandert het doel van "deployen zonder downtime" naar "meerdere client-generaties tegelijk werkend houden." In de praktijk duwt mobiel je vaak richting canary-achtig denken voor API's, zelfs als je blue-green voor infrastructuur gebruikt.
Backward compatible wijzigingen vs API-versionering
Meestal wil je backward compatible wijzigingen, omdat die oude en nieuwe apps hetzelfde endpoint laten gebruiken.
Voorbeelden van backward compatible wijzigingen: nieuwe velden toevoegen, zowel oude als nieuwe payloads accepteren, bestaande responsevelden behouden en de betekenis niet veranderen.
API-versionering wordt nuttig als het gedrag echt moet veranderen (niet alleen data toevoegen), of als je velden moet verwijderen of hernoemen.
Voorbeeld: een optioneel veld marketing_opt_in toevoegen is meestal veilig. Veranderen hoe price wordt berekend meestal niet.
Een deprecatie-window plannen
Als je een breaking change nodig hebt, behandel het einde van ondersteuning als een productbeslissing. Een nuttige deprecatieperiode meet je aan de hand van "actieve gebruikers die nog op oude versies zitten", niet in kalenderdagen.
Een praktisch verloop:
- Ship de backend die zowel oude als nieuwe clients ondersteunt.
- Release de nieuwe mobiele app en volg adoptie per appversie.
- Waarschuw of beperk pas wanneer oude versies onder een veilig drempeltje dalen.
- Verwijder het oude gedrag als laatste, met een rollback-plan.
Stapsgewijs: een veilig rollout-patroon voor API + database-wijzigingen
Als je tegelijk een API en een database verandert, is het veiligste plan meestal een rollout in twee of drie stappen. Elke stap moet op zichzelf veilig te deployen zijn, zelfs als gebruikers een oudere mobiele app blijven gebruiken.
Een rollout-patroon dat oude clients niet breekt
Begin met een additieve database-wijziging. Voeg nieuwe kolommen of tabellen toe, vermijd hernoemen of verwijderen, sta nulls toe waar nodig en gebruik defaults zodat oudere code niet plotseling op constraints stuit.
Deploy daarna applicatiecode die beide vormen van data tolereert. Reads moeten zowel "oud veld ontbreekt" als "nieuw veld aanwezig" accepteren. Writes blijven voorlopig het oude veld schrijven en kunnen optioneel ook het nieuwe veld vullen.
Een typisch verloop:
- Voeg nieuwe schema-onderdelen toe (kolommen, tabellen, indexes) zonder oude te verwijderen.
- Deploy code die van oud of nieuw leest en niet crasht op nulls.
- Backfill bestaande rijen in kleine batches en verifieer counts, null-ratio's en query-performance.
- Schakel het schrijfpad over naar het nieuwe veld, met fallback-reads.
- Nadat oudere mobiele versies verdwijnen, verwijder je het oude veld en ruim je code op.
Backfill en verificatie: waar outages zich verbergen
Backfills falen vaak omdat ze als een snel script worden behandeld. Run ze geleidelijk, monitor load en verifieer resultaten. Als het nieuwe gedrag een index nodig heeft, voeg die dan toe vóór je reads of writes overschakelt, niet erna.
Voorbeeld: je voegt phone_country_code toe voor betere formattering. Voeg eerst de kolom (nullable) toe, update de API om het te accepteren maar nog steeds te werken als het ontbreekt, backfill van bestaande telefoonnummers en begin daarna nieuwe aanmeldingen ermee te vullen. Weken later, wanneer oude appversies grotendeels verdwenen zijn, kun je de legacy parsing-path verwijderen.
Tools die beide strategieën veiliger maken (zonder ingewikkeld te worden)
Je hebt geen complexe setup nodig om blue-green of canary veiliger te maken. Een paar gewoonten verminderen verrassingen wanneer API's en databaseschema's in verschillend tempo bewegen.
Dual-read en dual-write (tijdelijk houden)
Dual-write betekent dat de app tijdens de overgang naar zowel de oude als de nieuwe plek schrijft (bijvoorbeeld zowel users.full_name als een nieuwe users.display_name). Dual-read betekent dat het van beide kan lezen, meestal voorkeur gevend aan het nieuwe veld maar met fallback naar het oude.
Dat koopt tijd voor trage client-updates, maar het moet een korte brug zijn. Bepaal hoe je het gaat verwijderen, track welk pad gebruikt wordt (nieuw vs fallback) en voeg basischecks toe om consistentie van beide writes te waarborgen.
Feature flags voor gedragswijzigingen
Feature flags laten je code deployen zonder het risicovolle gedrag aan te zetten. Dat helpt bij zowel blue-green als canary rollouts omdat je "deploy" kunt scheiden van "aanzetten".
Voorbeeld: deploy ondersteuning voor een nieuw response-veld, maar laat de server voorlopig de oude vorm teruggeven. Schakel dan het nieuwe gedrag aan voor een kleine groep, bekijk fouten en bouw het op. Als iets breekt, zet de flag uit zonder een volledige rollback.
Contract-testing mindset (de API is een belofte)
Veel migratie-incidenten zijn eigenlijk geen "databaseproblemen." Het zijn problemen met verwachtingswaarden van clients.
Beschouw de API als een belofte. Vermijd het verwijderen van velden of het veranderen van betekenis. Maak onbekende velden optioneel. Additieve wijzigingen (nieuwe velden, nieuwe endpoints) zijn meestal veilig. Brekende wijzigingen wachten op een nieuwe API-versie.
Data-migratie jobs die betrouwbaar zijn
Schema-migraties hebben vaak een backfill-job nodig om data te kopiëren, waarden te berekenen of op te schonen. Deze jobs moeten saai en herhaalbaar zijn: veilig om twee keer te draaien, retrybaar, makkelijk te tracken en gethrottled zodat ze geen load-pieken veroorzaken.
Veelgemaakte fouten die outages veroorzaken tijdens migraties
De meeste migratie-outages gebeuren wanneer een release ervan uitgaat dat alles tegelijk beweegt: alle services deployen tegelijk, alle data is schoon en alle clients updaten meteen. Echte systemen werken niet zo, vooral niet met mobiele clients.
Veelvoorkomende foutpatronen:
- Een kolom te vroeg droppen of hernoemen. Oude API-code, achtergrondjobs of oudere mobiele apps gebruiken die kolom mogelijk nog.
- Aannemen dat clients snel updaten. Mobiele releases doen er tijd over en veel gebruikers updaten niet meteen.
- Migraties uitvoeren die grote tabellen locken tijdens piekuren. Een "simpele" index- of kolomwijziging kan writes blokkeren.
- Alleen met schone sample-data testen. Productiedata bevat nulls, rare formaten, duplicaten en legacy-waarden.
- Geen echt rollback-plan voor code en data hebben. "We kunnen de vorige versie redeployen" is niet genoeg als het schema al veranderd is.
Voorbeeld: je hernoemt status naar order_status en deployt de nieuwe API. De webapp werkt. Oudere mobiele clients sturen nog status, en nu verwierp de API die requests, waardoor checkouts faalden. Als je de kolom had verwijderd, is gedrag herstellen geen snelle switch.
Een betere default is: verander in kleine, omkeerbare stappen, houd oude en nieuwe paden samen werkend en schrijf op wat je doet als metrics stijgen (hoe verkeer terug te routeren, welke feature flag het nieuwe gedrag uitzet en hoe je data valideert en repareert als een backfill misgaat).
Korte checklist voordat je deployt
Net voor een release vangt een korte checklist de problemen die tot late-night rollbacks leiden. Dit is vooral belangrijk als je tegelijk een API en database wijzigt, vooral met trage mobiele updates.
Vijf checks die de meeste outages voorkomen
- Compatibiliteit: bevestig dat oude en nieuwe appversies beide werken tegen hetzelfde databaseschema. Een praktische test is de huidige productie-build tegen een staging-database met de nieuwe migratie laten draaien.
- Migratievolgorde: zorg dat de eerste migratie additief is en plan destructieve wijzigingen (kolommen droppen, constraints verscherpen) later.
- Rollback: definieer de snelste undo. Voor blue-green is dat het terugschakelen van verkeer. Voor canary is dat 100% verkeer naar de stabiele versie sturen. Als rollback nog een migratie vereist, is het niet simpel.
- Performance: meet query-latenties na de schema-wijziging, niet alleen correctheid. Een ontbrekende index kan één endpoint doen voelen als een outage.
- Client realiteit: identificeer de oudste actieve mobiele appversie die nog je API aanroept. Als een betekenisvol percentage daarop zit, plan je een langere compatibiliteitsperiode.
Een korte sanity-scenario
Als je een nieuw veld zoals preferred_language toevoegt, deploy dan eerst de database-wijziging als nullable. Ship daarna servercode die het leest als het er is maar het niet vereist. Maak het pas verplicht of verwijder oudere paden wanneer de meeste traffic op geüpdatete apps zit.
Voorbeeld: een nieuw veld toevoegen zonder oudere mobiele apps te breken
Stel dat je een nieuw profielveld country toevoegt en het bedrijf wil het verplicht maken. Dat kan op twee plekken breken: oudere clients sturen het veld mogelijk niet, en de database kan writes afkeuren als je te vroeg NOT NULL afdwingt.
Een veiligere aanpak is twee aparte wijzigingen: eerst het veld additief en backward compatible toevoegen, later pas "verplicht" afdwingen als clients bijgewerkt zijn.
Hoe het er met blue-green uitziet
Met blue-green deploy je de nieuwe versie naast de oude. Je hebt nog steeds een compatibele database-wijziging nodig.
Een veilig verloop is:
- deploy de migratie (voeg
countrytoe als nullable) - deploy de green-versie die ontbrekend
countryaccepteert en een fallback gebruikt - test kernflows tegen green (signup, profiel bewerken, checkout)
- switch het verkeer
Als er iets misgaat, schakel je terug. Belangrijk is dat terugschakelen alleen werkt als het schema nog steeds de oude versie ondersteunt.
Hoe het er met canary uitziet
Met canary stel je het nieuwe API-gedrag eerst bloot aan een klein deel (vaak 1% tot 5%) en let je op validatie-fouten voor missende velden, latentieveranderingen en onverwachte database-fouten.
Een veelvoorkomende verrassing is dat oudere mobiele clients profielupdates zonder country sturen. Als de API het meteen verplicht stelt, zie je 400-fouten. Als de database NOT NULL afdwingt, zie je mogelijk 500-fouten.
Een veiliger sequentie:
- voeg
countrytoe als nullable (optioneel met een veilige default zoals "unknown") - accepteer ontbrekend
countryvan oudere clients - backfill
countryvoor bestaande gebruikers met een achtergrondjob - handhaaf "verplicht" later (eerst in de API, dan in de database)
Documenteer na de release wat oude clients kunnen sturen en wat de server garandeert. Dat geschreven contract voorkomt dezelfde breuk bij de volgende migratie.
Als je bouwt met AppMaster (appmaster.io), geldt dezelfde uitroldiscipline, ook al kun je backend, web en native mobiele apps vanuit één model genereren. Gebruik het platform om additieve schema-wijzigingen en tolerante API-logica eerst te shippen, en verscherp constraints pas nadat adoptie is gestegen.
FAQ
Blue-green draait twee complete omgevingen en schakelt al het verkeer ineens om. Canary zet de nieuwe versie eerst live voor een klein percentage en bouwt dat percentage op op basis van wat je in productie ziet.
Gebruik blue-green wanneer je een schone cutover wilt en je zeker weet dat de nieuwe versie compatibel is met het huidige databaseschema. Het is vooral nuttig als het grootste risico in de applicatiecode zit en je voorspelbaarheid nodig hebt.
Gebruik canary wanneer je wilt leren van echt verkeer voordat je volledig uitrolt — bijvoorbeeld als querypatronen, edge-case data of achtergrondjobs anders kunnen reageren in productie. Het verkleint de blast radius, maar je moet metrics goed in de gaten houden en klaar zijn om de uitrol te stoppen.
Nee. Als de schema-wijziging compatibiliteit breekt (zoals het verwijderen of hernoemen van een kolom die oude code nog gebruikt), kunnen zowel blue-green als canary falen. De veiligere aanpak is een online migratie ontwerpen die oude en nieuwe versies tegelijk ondersteunt.
Mobiele gebruikers blijven vaak weken op oudere versies, dus je backend moet meerdere client-generaties tegelijk ondersteunen. Dat betekent meestal dat API's langer backward compatible moeten blijven en dat je geen wijzigingen kunt doen die alle clients meteen laten updaten.
Begin met additieve wijzigingen die oude code kan negeren, zoals het toevoegen van nullable kolommen of nieuwe tabellen. Deploy code die zowel oude als nieuwe datavormen aankan, backfill geleidelijk, schakel gedrag over en verwijder pas later oude velden of verscherp constraints.
Maak een lijst van wat oude clients sturen en verwachten, en verwijder geen velden of verander hun betekenis. Voeg bij voorkeur nieuwe optionele velden toe, accepteer zowel oude als nieuwe request-shapes en wacht met het afdwingen van "vereist" totdat adoptie hoog genoeg is.
Dual-write schrijft tijdens de overgang naar zowel het oude als het nieuwe veld, en dual-read leest het nieuwe veld met een fallback naar het oude. Gebruik dit tijdelijk, track welke pad gebruikt wordt en plan een duidelijk opruimmoment zodra oudere clients verdwijnen.
Feature flags laten je code deployen zonder het risicovolle gedrag direct te activeren. Daarmee kun je uitrol en activatie scheiden: zet de feature aan voor een kleine groep, monitor fouten en zet hem uit als het misgaat, zonder een volledige rollback.
Te vroeg een kolom verwijderen of hernoemen, een NOT NULL afdwingen voordat clients de waarde sturen, en blocking migraties tijdens piekuren zijn veelvoorkomende oorzaken. Ook het vertrouwen op schoon testdata in plaats van reële productie-data leidt tot mislukte backfills en onverwachte fouten.


