12 apr 2025·7 min leestijd

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.

Blue-green vs canary-implementaties: veiligere API- en databasewijzigingen

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

Host zelf wanneer nodig
Exporteer gegenereerde broncode voor self-hosting wanneer je volledige controle over deployments nodig hebt.
Exporteer code

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

Houd API's backward compatible
Maak endpoints en businesslogica die oude en nieuwe client-payloads kunnen verwerken.
Bouw backend

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

Hanteer trage mobiele updates
Bouw mobiele apps die compatibel blijven terwijl gebruikers over dagen of weken updaten.
Maak app

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

Plan online migraties
Ontwerp additieve schema-updates in PostgreSQL met een duidelijk pad voor later opruimen.
Aan de slag

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 country toe als nullable)
  • deploy de green-versie die ontbrekend country accepteert 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 country toe als nullable (optioneel met een veilige default zoals "unknown")
  • accepteer ontbrekend country van oudere clients
  • backfill country voor 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

Wat is het eenvoudigste verschil tussen blue-green en canary deployments?

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.

Wanneer moet ik blue-green kiezen voor een API + database wijziging?

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.

Wanneer is canary de veiligere optie?

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.

Maken blue-green of canary database-migraties automatisch veilig?

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.

Waarom maken trage mobiele app-updates deployments riskanter?

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.

Wat is de veiligste manier om een schema-wijziging uit te rollen zonder downtime?

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.

Hoe houd ik mijn API backward compatible tijdens een migratie?

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.

Wat zijn dual-read en dual-write en wanneer moet ik ze gebruiken?

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.

Hoe verminderen feature flags het risico tijdens API- of DB-wijzigingen?

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.

Wat zijn de meest voorkomende migratiefouten die outages veroorzaken?

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.

Gemakkelijk te starten
Maak iets geweldigs

Experimenteer met AppMaster met gratis abonnement.
Als je er klaar voor bent, kun je het juiste abonnement kiezen.

Aan de slag