Je WMS meldt om 09:00 uur 86 verkoopbare stuks. Zeven seconden later reserveert een order er twaalf, maar je synchronisatiewerker schrijft nog steeds de oude voorraad naar Shopify. De API antwoordt met 200 OK. Je webshop toont nu een getal dat technisch is opgeslagen en toch inhoudelijk fout is.
Deze gids is voor e-commerce- en operationsverantwoordelijken, integratiebouwers en ontwikkelaars die voorraad, orders of financiële statussen tussen meerdere systemen publiceren. Je hebt er vooral iets aan wanneer een verkeerde write een klantbelofte, voorraadpositie of boeking kan raken en je wilt kunnen aantonen waarom een wijziging wel of niet is vrijgegeven.
Dit is een stale write: een oudere lezing overschrijft een nieuwere werkelijkheid. De oplossing is geen extra retry. Je hebt bronhouderschap, een versie op de bron, een voorwaardelijke write, een read-back en een zichtbaar besluit nodig voor alles wat niet meer veilig automatisch kan.
Versioned data-sync is een synchronisatie waarin iedere wijziging een bronversie, sleutel en peiltijd meedraagt. Voor het schrijven controleert de verwerker of de bron nog dezelfde versie heeft. Na het schrijven leest hij het doel opnieuw uit. Alleen wanneer bron, write en read-back bij elkaar passen, wordt de wijziging vrijgegeven.
De bredere datagrens begint bij bronhouderschap per veld en reconciliatie. Hier zoom ik in op het gevaarlijke moment daarna: de oude waarde ligt al klaar om geschreven te worden, maar de bron is ondertussen veranderd.
Wat je nodig hebt voordat je begint
Maak eerst een klein gegevenscontract. Een synchronisatie tussen Shopify, een WMS en Exact Online is geen enkele stroom. De order, de voorraad, de betaling en de factuur hebben elk een eigen bronhouder.
Maak vóór de uitvoering deze randvoorwaarden concreet:
| Onderdeel | Minimum vóór stap 1 |
|---|---|
| Accounts | API- of beheertoegang tot WMS, Shopify, ERP en workflow- of opslaglaag; webhookbeheer en rechten om doelwaarden terug te lezen. |
| Rollen | Eén bronverantwoordelijke per veld, één technisch eigenaar voor de sync en één operationsverantwoordelijke die risicovolle queue-items mag sluiten. |
| Budgetorde | Een pilot met bestaande accounts kost meestal enkele duizenden euro's; productie met eigen ledger, read-back, reconciliatie en vrijgave zit eerder rond €10.000 tot €25.000 eenmalig, plus licentie, infrastructuur en beheer. Dit is een indicatie, geen offerte. n8n Cloud staat op 16 oktober 2026 op €20 per maand bij jaarlijkse facturatie voor 2,5K executions, €50 voor 10K en €667 voor 40K. |
| Gegeven | Bronhouder in dit voorbeeld | Stabiele sleutel | Mag naar doel schrijven? |
|---|---|---|---|
| Verkoopbare voorraad per locatie | WMS | SKU plus locatie | Ja, naar verkoopkanaal |
| Order en orderregels | Shopify | Order-ID plus regel-ID | Ja, naar WMS en ERP |
| Betaalstatus | Stripe of Mollie | Payment-ID | Alleen als afgeleide status |
| Factuur en boeking | Exact Online of Moneybird | Boeking-ID plus order-ID | Niet terug naar de bronvelden |
| Synchronisatiesnapshot | Eigen datalaag | Snapshot-ID | Ja, als bewijs van de run |
| Vrijgavebesluit | Bevoegde medewerker | Decision-ID | Nee, dit is een auditrecord |
Leg per veld vast:
- Bronhouder: het systeem dat de waarde kan bewijzen en mag beslissen.
- Definitie: bijvoorbeeld verkoopbare voorraad na reserveringen, niet simpelweg fysiek aanwezig.
- Sleutel: een interne ID, order-ID, payment-ID of SKU plus locatie. Gebruik een e-mailadres of productnaam niet als enige sleutel.
- Bronversie: een oplopende versie zoals wms-731, een ETag of een inhoudshash. Een tijdstip alleen is te zwak.
- Versheidsgrens: bijvoorbeeld vijf minuten voor webshopvoorraad of één uur voor een rapportage-export. Dit is beleid, geen universele technische norm.
- Doelactie: welke velden worden geschreven, welke velden nooit terug mogen naar de bron en welke transformaties zijn toegestaan.
- Vrijgavebeleid: welke afwijkingen software zelf mag herstellen en welke eerst door een mens worden beoordeeld.
Je hebt ook een eigen plek nodig voor snapshots, verwerkingspogingen, idempotentiesleutels en uitzonderingen. De uitvoergeschiedenis van n8n of Make is geen duurzaam bewijs van wat er in Shopify of je ERP is gebeurd. Bewaar minimaal de bronversie, de payload of payloadverwijzing, de hash, het doel-ID, de status, de laatste fout en de naam van de vrijgever.
Voor de eerste proef heb je geen complete migratie nodig. Gebruik 20 tot 50 records en voeg bewust deze gevallen toe:
- een dubbele webhook;
- een event dat te laat binnenkomt;
- een bronwijziging tijdens de berekening;
- een timeout na een externe write;
- een doelrecord met een andere waarde;
- een record zonder geldige sleutel;
- een wijziging die geld, voorraad of een klantbelofte raakt.
De technische details en publieke prijzen in deze gids zijn gecontroleerd op 16 oktober 2026. De bouw vraagt naast API-toegang ook iemand die de uitzonderingsqueue werkelijk mag sluiten. Zonder die persoon automatiseer je vooral het verplaatsen van onzekerheid.
Concrete stappen: van bronwijziging naar veilige vrijgave
1. Wijs bronhouderschap en bronversie toe
Begin met het veld, niet met de applicatie. Voor een voorraadbelofte kan het WMS de bronhouder zijn, terwijl Shopify alleen de afgeleide publicatie toont. Voor de order is Shopify de bronhouder. Voor de factuur kan Exact Online dat zijn.
Maak de bronversie onderdeel van iedere snapshot:
| Veld | Voorbeeld |
|---|---|
| snapshot_id | snap-2026-10-16-0042 |
| business_key | SKU-P400:ROTTERDAM |
| source_system | WMS |
| source_version | wms-731 |
| captured_at | 2026-10-16 09:00:00+02:00 |
| fresh_until | 2026-10-16 09:05:00+02:00 |
| payload_hash | sha256:... |
| formula_version | voorraad-v3 |
| risk_class | voorraadbelofte |
Een oplopende versie is sterker dan updated_at. Twee wijzigingen kunnen dezelfde seconde delen. Een versie kan ook door een externe API worden geleverd als ETag. Gebruik een hash wanneer de bron geen teller heeft, maar leg vast welke inhoud je hebt gehasht en hoe je omgaat met verschillende veldvolgorde.
Zet per bron vast hoe je een nieuwe versie herkent. Een WMS kan dat doen per SKU en locatie, een ERP per record of batch. Meng versies niet stilletjes. wms-731 en wms-batch-731 zijn alleen vergelijkbaar als je contract dat zegt.
2. Maak het synchronisatiecontract uitvoerbaar
Een contract is pas bruikbaar als je het kunt testen met een concreet record. Neem minimaal op:
- welke gebeurtenis de flow start;
- welke bronversie bij die gebeurtenis hoort;
- welke records de verwerker opnieuw moet ophalen;
- welke velden worden berekend;
- welke precondities voor de write gelden;
- welke response als succes geldt;
- hoe read-back wordt uitgevoerd;
- hoe een onbekende uitkomst naar de queue gaat;
- wie een conflict mag vrijgeven.
Voorraad is een goed voorbeeld. Stel dat het WMS 86 verkoopbare stuks meldt, 27 hard reserveert, 6 tijdelijk vasthoudt en 10 als veiligheidsbuffer markeert. De verkoopbare belofte is dan:
86 - 27 - 6 - 10 = 43
Bewaar de onderdelen, niet alleen het getal 43. Als de uitkomst later 31 wordt, moet je kunnen aanwijzen of er een nieuwe order, verlopen reservering, telling of beleidswijziging achter zit. Een versioneerbare leverbelofte uit WMS-data trekt dit voorraadmodel door naar meerdere kanalen.
Neem ook de negatieve route op. Als de bronversie ontbreekt, het record te oud is of de formule een negatieve uitkomst geeft, schrijf je niet alvast een nul naar het kanaal. Je maakt een uitzonderingsrecord met een reden.
3. Ontvang events, maar vertrouw ze niet blind
Een webhook is een signaal om actuele brondata op te halen. Het is niet automatisch de volledige waarheid en ook geen bewijs dat jouw verwerking geslaagd is.
Bij Shopify bevat iedere HTTPS-delivery een HMAC-signatuur en een delivery-ID. De actuele Shopify-documentatie schrijft voor dat je de ruwe body verifieert en de delivery-ID gebruikt om dubbele afleveringen te herkennen. Sla de event-ID op voordat je het bedrijfs-effect uitvoert. Antwoord snel en verwerk de zware API-calls buiten de HTTP-aanvraag.
De herstelgrens is productafhankelijk. Shopify probeert een mislukte webhook maximaal acht keer binnen vier uur en kan daarna de subscription verwijderen. Die retry-regel en de noodzaak van een bronimport na uitputting van retries staan in de Shopify-herstelhandleiding. Bouw daarom naast de webhook altijd een periodieke vergelijking of backfill.
Stripe gebruikt weer andere haken. De actuele Stripe-documentatie, gecontroleerd op 16 oktober 2026, zegt dat onbezorgde events tot drie dagen automatisch opnieuw worden geprobeerd en dat de Events API alleen de laatste dertig dagen teruggeeft. Je kunt met delivery_success=false de mislukte events selecteren. De herstelroute markeert events eerst als in behandeling, voorkomt dubbele verwerking en geeft na een al verwerkt event HTTP 200 terug.
De Stripe API-documentatie, gecontroleerd op 16 oktober 2026, adviseert voor muterende aanvragen een idempotentiesleutel. Bij API v1 bewaart Stripe het eerste resultaat per sleutel en kunnen sleutels na minstens 24 uur automatisch worden verwijderd. Gebruik dezelfde sleutel voor dezelfde retry en maak pas een nieuwe sleutel wanneer je bewust een nieuwe zakelijke handeling start.
Maak in je eigen opslag onderscheid tussen:
- delivery_id: één aflevering;
- source_object_id: het object bij Shopify, Stripe, Mollie of het ERP;
- business_key: de handeling in jouw proces;
- idempotency_key: de unieke opdracht voor één doelactie;
- attempt_id: één poging van jouw verwerker.
Dat onderscheid voorkomt dat twee unieke event-ID’s dezelfde financiële of voorraadactie nog een keer uitvoeren. Bij financiële gebeurtenissen geldt dezelfde regel: replay hoort dezelfde handeling te herkennen voordat hij een tweede boeking maakt.
4. Blokkeer stale writes met optimistic concurrency
Optimistic concurrency betekent dat je geen lange database-lock vasthoudt tijdens een API-flow. Je leest een versie, berekent een voorstel en schrijft alleen wanneer die versie nog actueel is.
De officiële Ed-Fi-richtlijn, bijgewerkt op 8 december 2024 en opnieuw gecontroleerd op 16 oktober 2026, beschrijft dit met ETag en If-Match. De server voert de write alleen uit wanneer de ETag nog overeenkomt. Bij een verschil volgt HTTP 412, zodat een oude lezing niet de nieuwste waarde overschrijft. De richtlijn noemt dit expliciet als bescherming tegen last-in-wins en gegevensverlies.
Heeft je externe API een source-side CAS of If-Match-contract dat de hele publiceeractie afdekt, gebruik dat als echte atomische laatste poort. De publisher geeft dan bijvoorbeeld expected_source_version: wms-731 mee aan een WMS-backed write-service. Die service vergelijkt de bronversie in dezelfde commit als het uitgeven van de publicatietoestemming en weigert bij een verschil met 412; zonder geldige toestemming gaat er geen Shopify-request uit. Een target-side versiecheck is ook alleen atomisch als het doel de actuele bronversie kent en een lagere binnenkomende source_version in dezelfde write afwijst.
De SQL hieronder is iets anders: een lokale compare-and-swap op de eigen publicatieregel. Tussen deze transactie en de externe request kan het WMS nog veranderen. Als Shopify of je WMS-backed publisher geen bronversie-preconditie tot aan de externe write kan afdwingen, noem je deze route expliciet best-effort en voer je na de write nog een broncheck uit:
UPDATE channel_publication
SET status = 'ready_to_write',
source_version = 'wms-731'
WHERE publication_id = 'pub-2026-10-16-0042'
AND source_version = 'wms-731'
AND status = 'draft';
Een best-effort route mag een write dus pas als verified markeren wanneer zowel de pre-write bronversie als de post-write bronversie wms-731 zijn. Is de tweede lezing wms-732, markeer je source_changed_after_write, zet je de publicatie op superseded of invalidated en maak je een nieuwe snapshot voor de actuele bron. De oude doelwaarde kan kort zichtbaar zijn geweest, maar wordt niet als veilige publicatie geaccepteerd.
De actuele Shopify InventoryLevel-documentatie, geraadpleegd op 16 oktober 2026, beschrijft voor voorraad per locatie de acties available en available_adjustment en toont updated_at, maar geen If-Match-preconditie voor de bronversie. Daarom is Shopify in dit voorbeeld geen atomische bronpoort. RFC 9110 uit 2022, geraadpleegd op 16 oktober 2026, beschrijft If-Match als een preconditie voor state-changing requests en als bescherming tegen lost updates.
PostgreSQL 18 is op 15 oktober 2026 de actuele documentatieversie. De handleiding maakt duidelijk dat Read Committed standaard is en dat een tweede update de WHERE-voorwaarde opnieuw beoordeelt op de bijgewerkte rij. Gebruik die transactieregels als basis voor de lokale claim, maar presenteer die claim nooit als een cross-system lock.
Verwar drie begrippen niet:
- Bronversie: beschermt je tegen een voorstel dat op oude data is berekend.
- Idempotentiesleutel: beschermt je tegen het uitvoeren van dezelfde opdracht op dezelfde doelactie.
- Post-write broncheck en read-back: controleren samen of de bron na de externe write nog bij de gepubliceerde doeltoestand past.
Je hebt ze alle drie nodig. Een idempotente retry kan nog steeds een stale snapshot schrijven. Een lokale versiecheck kan de write niet blokkeren nadat de bron tussen de check en het externe verzoek verandert. Zonder atomische bron- of doelpreconditie is de post-write broncheck daarom verplicht.
5. Schrijf één keer en lees het doel terug
De veilige volgorde is:
- Lees bronrecord en bronversie.
- Bereken een immutable snapshot.
- Controleer versheid en beleid.
- Maak een verwerkingsrecord met een vaste idempotentiesleutel.
- Voer de source-side CAS/If-Match uit als die de hele publiceeractie afdekt; registreer anders dat de route best-effort is.
- Schrijf naar het doel.
- Sla response, doel-ID en tijdstip op.
- Lees het doel terug met de stabiele sleutel.
- Lees de bronversie opnieuw. Bij een verschil markeer je
source_changed_after_writeen accepteer je de write niet als verified. - Vergelijk de afgesproken velden, versie en publicatie-ID. Markeer alleen verified als de bron voor en na de write gelijk is; anders gaat het geval naar de uitzonderingsqueue.
Een HTTP 200 is dus een transportresultaat. Het zegt niet altijd dat de juiste locatie, rij of asynchrone verwerking is geraakt.
Definieer per doel wat read-back betekent. Bij een directe database-write vergelijk je de opgeslagen rij. Bij Shopify haal je de actuele inventorywaarde op voor de juiste SKU en locatie. Bij een ERP controleer je de doelreferentie, status en relevante bedragen. Bij een asynchrone API wacht je een begrensde periode, lees je opnieuw en geef je daarna een write_unconfirmed-besluit als de toestand onbekend blijft.
Bij de best-effort route is de post-write broncheck geen extra retry en geen cosmetische logregel. Als de bronversie na de write is veranderd, verklaar je de publicatie ongeldig, laat je een nieuwe snapshot rekenen en houd je de oude publicatie als superseded bewijs vast. Alleen wanneer broncheck, doel-read-back en payloadhash bij elkaar passen, sluit je de poging als verified.
Schrijf nooit opnieuw zodra een timeout optreedt. Zoek eerst op jouw publication_id of idempotentiesleutel naar het doelresultaat. Als de API geen eigen sleutel kan bewaren, gebruik je een eigen ledger en zoek je op de combinatie van zakelijke sleutel, bronversie en doelstatus. Blijft het antwoord onzeker, dan is een mens goedkoper dan een dubbele boeking of een verkeerde voorraadbelofte.
6. Bewaar herstelbewijs en maak de queue beslisbaar
Een uitzonderingsqueue is geen afvalbak voor foutmeldingen. Ieder item heeft een concrete reden, eigenaar, deadline en toegestane beslissing.
Gebruik bijvoorbeeld deze redencodes:
| Reden | Betekenis | Eerste actie |
|---|---|---|
| source_version_conflict | Bron veranderde tijdens de flow | Nieuwe snapshot ophalen |
| source_changed_after_write | Bron veranderde tussen externe write en post-write broncheck | Publicatie ongeldig verklaren en nieuwe snapshot ophalen |
| source_stale | Snapshot is over de versheidsgrens | Berekening opnieuw uitvoeren |
| write_timeout | Doelresultaat is onbekend | Doel opzoeken, niet opnieuw schrijven |
| read_back_mismatch | Doelwaarde wijkt af van voorstel | Doelstatus en bron vergelijken |
| duplicate_candidate | Dezelfde zakelijke actie lijkt al verwerkt | Ledger en doelreferentie controleren |
| key_missing | Record kan niet veilig worden gekoppeld | Menselijke match |
| policy_blocked | Waarde raakt geld, voorraad of klantbelofte | Bevoegde vrijgave |
Bewaar bij iedere poging:
- bron- en doelreferentie;
- oude en nieuwe waarde;
- bronversie en snapshot-ID;
- idempotentiesleutel;
- request- en responsehash;
- statuscode en fouttekst;
- pogingnummer en volgende poging;
- actor, tijdstip en beslissing;
- reden waarom automatische vrijgave wel of niet mocht.
NIST SP 800-53 Rev. 5 is in september 2020 gepubliceerd en kreeg op 27 augustus 2025 release 5.2.0. De auditcontrole AU-3 noemt gebeurtenistype, tijdstip, bron, uitkomst en identiteit als onderdelen van een bruikbaar auditrecord. Gebruik dat als ontwerpchecklist voor je herstelbewijs, niet als vervanging van je eigen bedrijfsbeleid.
7. Reconcileer vóór en na de vrijgave
Reconciliatie is je vangnet voor gemiste events, late responses en stille verschillen. Plan minstens vier controles:
- Telling: hoeveel bronrecords, snapshots, doelrecords en queue-items bestaan er?
- Sleutelset: welke zakelijke sleutels staan alleen aan bron- of doelzijde?
- Waarde: welke velden wijken af, met welke bronversie?
- Bedrijfstotaal: sluiten voorraad, betaalde orders, facturen of kanaalquota aan?
Voer dezelfde controle uit vóór productie, na een herstelrun en na de eerstvolgende volledige cyclus. Laat een vrijgave pas doorgaan als de bronversie geldig is, de write bekend is, de read-back klopt en het record niet in een risicocategorie valt.
De minimale vrijgavebeslissing bevat:
- wat de software heeft voorgesteld;
- welke bronversie daarvoor is gebruikt;
- wat het doel teruglas;
- welke afwijking is gevonden;
- welke actie de medewerker kiest;
- wie dat besluit nam;
- waarom het besluit binnen het beleid valt.
Na deze stappen zie je de echte omvang van de klus. De API-aanroep is het korte deel. Het moeilijke werk zit in de bronversie, de tweede controle, de terugleesproef en het besluit wanneer onzekerheid niet langer automatisch mag worden doorgeschoven.
Valkuilen die je synchronisatie onbetrouwbaar maken
Je gebruikt updated_at als enige versie
Een timestamp kan dezelfde precisie hebben als twee snelle wijzigingen. Hij zegt ook niet altijd welke velden veranderden of of de bronwaarde al is verwerkt.
Mitigatie: gebruik een oplopende versie, ETag of inhoudshash. Bewaar de bronversie in de snapshot en vergelijk die vlak voor de write opnieuw.
Je behandelt HTTP 200 als inhoudelijk succes
200 bewijst dat je endpoint een antwoord kreeg. Het bewijst niet dat de juiste locatie, rij of asynchrone verwerking klaarstaat.
Mitigatie: sla het doelresultaat op, lees de doelwaarde terug en gebruik een aparte status verified. Een onbekende toestand gaat naar write_timeout of read_back_pending, niet naar success.
Je maakt bij een retry een nieuwe sleutel
Daarmee maak je van dezelfde onzekere handeling een nieuwe opdracht. Dat kan dubbele voorraad, dubbele facturen of twee refunds opleveren.
Mitigatie: behoud de idempotentiesleutel bij een retry. Maak alleen een nieuwe sleutel wanneer een bevoegde medewerker bewust een nieuwe zakelijke correctie vrijgeeft.
Je leest alleen het doel terug
Een doelwaarde kan gelijk lijken terwijl de bron ondertussen alweer een nieuwe versie heeft. Dan heb je een oude publicatie correct gecontroleerd en toch een verouderde belofte.
Mitigatie: lees de bron ook ná de write terug. Zonder atomische preconditie is een veranderde bronversie source_changed_after_write: accepteer de doelwaarde niet als verified, maak een nieuwe snapshot en houd de oude publicatie als superseded bewijs vast.
Je laat last-in-wins conflicten oplossen
De laatste schrijver is niet automatisch de bronhouder. Een nachtelijke import kan een handmatige correctie overschrijven omdat hij later draaide.
Mitigatie: leg per veld de eigenaar vast. Blokkeer writes vanuit afgeleide systemen en gebruik source_version_conflict als reden voor menselijke beoordeling.
Je stopt alles in één brede queue
Een timeout op een leesactie vraagt een andere actie dan een mogelijke dubbele boeking. Een medewerker die alleen sync failed ziet, kan geen veilige beslissing nemen.
Mitigatie: werk met redencodes, een eigenaar, een deadline en een beperkte lijst toegestane acties. Toon de oude waarde, nieuwe waarde, bronversie en het laatste read-back-resultaat.
Je gebruikt de workflowtool als audittrail
n8n en Make zijn nuttig voor triggers, transformaties en meldingen. Hun uitvoeringslog is niet automatisch jouw bewijs dat een doelrecord later nog terugvindbaar is.
Mitigatie: schrijf snapshots, ledgerregels en vrijgavebesluiten naar een duurzame datalaag. Laat de workflowtool daaruit lezen en daarop terugvallen.
Je herstelt een gat met een volledige import
Een volledige import kan geldige nieuwe wijzigingen opnieuw aanbieden en oude waarden terugschrijven.
Mitigatie: bepaal het herstelvenster, laad met overlap, gebruik dezelfde idempotente verwerker en vergelijk de sleutelset. Herstel alleen wat aantoonbaar ontbreekt of opnieuw moet worden berekend.
Het beslis-kader: native koppeling, workflowlaag of maatwerk?
Kies de route op basis van de zwaarste uitzondering, niet van het gemiddelde aantal events. Een stroom met 100 writes per dag en één onomkeerbare fout kan meer controle vragen dan een stroom met 10.000 veilige statusupdates.
Kies een native of kant-en-klare koppeling wanneer
- één systeem bronhouder is;
- de richting vaststaat;
- writes omkeerbaar zijn;
- er geen bronversieconflicten tussen meerdere schrijvers ontstaan;
- read-back en logging aantoonbaar beschikbaar zijn;
- een menselijke vrijgave geen normaal onderdeel van het proces is.
Controleer de connector op concrete punten. Kan hij een delivery-ID bewaren? Kan hij een bestaande doelactie herkennen? Kan hij een write na timeout terugvinden? Kan hij het verschil tussen processed, verified en needs_review bewaren? Als het antwoord nee is, is de connector misschien snel gestart maar niet geschikt voor deze job.
Kies een workflowlaag met eigen opslag wanneer
- meerdere API's samenkomen;
- de regels stabiel zijn;
- je een technische beheerder hebt;
- de queue beperkt en voorspelbaar blijft;
- je zelf snapshots, idempotentie en read-back in een database vastlegt.
Gebruik n8n of Make dan als orkestrator. Laat de duurzame gegevens buiten de workflowhistorie staan. Voor een eenvoudige orderstroom kan dit de beste verhouding tussen snelheid en controle geven.
Kies maatwerk wanneer
- meerdere systemen hetzelfde veld kunnen wijzigen;
- stale writes geld, voorraad of een klantbelofte raken;
- je externe API's verschillend omgaan met retries en asynchrone writes;
- elke afwijking een bewijsdossier of bevoegd besluit vraagt;
- je bronversies, read-back, herstelruns en auditrecords over meerdere jaren wilt bewaren;
- je meerdere entiteiten, valuta, locaties of boekingsregels combineert.
Maatwerk betekent hier niet dat elk onderdeel nieuw moet worden gebouwd. Shopify, Stripe, Exact Online, Moneybird, n8n en Make kunnen onderdelen blijven leveren. De eigen laag bewaakt de zakelijke sleutel, versie, vrijgave en herstelbaarheid.
Kan een stale write geld, voorraad of een klantbelofte verkeerd zetten?
De keuzehulp geeft dezelfde drie uitkomsten als het geschreven kader. Het verschil zit niet in de naam van de tool, maar in de vraag of je de toestand na een write kunt bewijzen en wie een conflict mag sluiten.
Uitgewerkt voorbeeld: Shopify, WMS en Exact Online
Dit is een fictief oefenscenario met echte productnamen en voorbeeldwaarden. De webshop gebruikt Shopify, het magazijn een WMS, de financiële administratie Exact Online en n8n als workflowlaag. Het WMS blijft eigenaar van verkoopbare voorraad. Shopify bezit ordercreatie. Exact Online bezit de factuur en boeking.
De eerste snapshot
Op 16 oktober 2026 om 09:00 uur leest de workflow voor SKU P-400 in Rotterdam:
- verkoopbare voorraad: 86;
- hard gereserveerd: 27;
- tijdelijk gereserveerd: 6;
- veiligheidsbuffer: 10;
- berekende voorraadbelofte: 43.
De webshop mag door een kanaalregel maximaal 35 tonen. De snapshot krijgt:
- snapshot_id: snap-2026-10-16-0042;
- source_version: wms-731;
- business_key: P-400:ROTTERDAM;
- publication_id: pub-2026-10-16-0042;
- fresh_until: 09:05 uur;
- idempotency_key: wms-731:shopify:P-400:ROTTERDAM.
De worker maakt een voorstel voor Shopify met waarde 35. Op dit moment is er nog niets geschreven.
De stale write
Om 09:00:07 komt een nieuwe Shopify-order binnen voor twaalf stuks. Het WMS verwerkt de reservering en gaat van wms-731 naar wms-732. De nieuwe hard reservation is 39. De actuele berekening is:
86 - 39 - 6 - 10 = 31
De oude worker doet eerst de lokale claim met bronversie wms-731. Daarna verandert het WMS, buiten de lokale transactie om, naar wms-732. Shopify heeft in deze route geen If-Match voor de WMS-versie, dus de request voor waarde 35 kan nog een 200 OK geven. De verplichte post-write broncheck leest wms-732 en markeert de publicatie als source_changed_after_write. De waarde 35 wordt niet verified, de publicatie gaat op superseded of invalidated en er komt geen retry met dezelfde oude snapshot.
De queue bevat:
| Veld | Waarde |
|---|---|
| Reden | source_changed_after_write |
| Oude snapshot | snap-2026-10-16-0042 |
| Oude voorstel | 35 |
| Actuele bronversie na write | wms-732 |
| Nieuwe berekening | 31 |
| Eigenaar | Operations |
| Actie | Oude publicatie ongeldig verklaren en snapshot opnieuw berekenen |
| Bewijs | bronlog, reserverings-ID, lokale claim, Shopify-response, broncheck na write en oude en nieuwe formule |
De veilige publicatie
De workflow maakt een nieuwe snapshot met wms-732. De centrale voorraadbelofte is 31. De kanaalquota worden 25 voor Shopify, 4 voor een marketplace en 2 voor een B2B-portaal.
De write naar Shopify gebruikt de nieuwe publicatie-ID. De API antwoordt met succes. De worker leest de voorraad voor SKU P-400 en de juiste locatie terug. De waarde is 25. Ook de lokale publicatieregel staat op wms-732, de payloadhash komt overeen en de post-write broncheck bevestigt wms-732. Er is geen open conflict. De status wordt verified.
Als Shopify alleen de doelwaarde teruggeeft en geen eigen bronversie toont, blijft de versiecontrole in de eigen publicatielaag staan. De read-back bewijst dan de doelwaarde. De eigen ledger bewijst op welke bronversie die waarde mocht worden gepubliceerd.
Een tweede fout: onbekende write
Stel dat de tweede write na het versturen een timeout geeft. De worker maakt dan geen derde idempotentiesleutel. Hij zoekt eerst op pub-2026-10-16-0043 en de doelwaarde. Vindt hij 25, dan legt hij de doelreferentie en het tijdstip vast en voert hij alsnog de post-write broncheck uit. Alleen als het WMS nog wms-732 meldt en de payloadhash klopt, sluit hij de write als verified. Vindt hij 35, niets of een nieuwe bronversie, dan blijft de status write_unconfirmed of source_changed_after_write en gaat het record naar Operations.
De medewerker ziet de actuele WMS-versie, de publicatie, de Shopify-read-back, het verschil en de voorgestelde acties. Hij kan de oude publicatie ongeldig verklaren, een nieuwe snapshot laten rekenen of besluiten dat de kanaalwaarde handmatig wordt geblokkeerd. Elke keuze krijgt een actor, tijdstip en reden.
Het herstelbewijs
Na de run controleert de reconciliatie:
- de sleutel P-400:ROTTERDAM staat in WMS, de snapshotlaag en Shopify;
- de actieve Shopify-publicatie verwijst naar wms-732;
- 25 plus 4 plus 2 is 31, gelijk aan de actuele centrale belofte;
- de oude publicatie met waarde 35 staat als superseded in de audittrail;
- de queue bevat geen ongesloten stale write meer.
Het resultaat is niet alleen een groen scherm. Je kunt aantonen waarom 35 niet is gepubliceerd, welke bronwijziging dat veroorzaakte en waarom 25 na read-back wel mocht blijven staan.
Vergelijkingstabel: welke bouwroute past bij deze klus?
De productdetails en prijsinformatie in deze tabel zijn gecontroleerd op 16 oktober 2026. Publieke licentieprijzen zijn geen totale projectprijs. Opslag, monitoring, ontwerp, testen en beheer blijven afzonderlijke posten.
| Route | Actuele productdetails | Versie en read-back | Prijsbeeld | Past wanneer |
|---|---|---|---|---|
| Native connector | Shopify, Exact Online of een andere leverancier levert de koppeling | Alleen geschikt als delivery-ID, stale conflict, read-back en herstel aantoonbaar zijn | Leveranciersprijs of abonnement, per koppeling controleren | Eén bron, vaste richting en lage foutkosten |
| n8n Cloud | Starter: €20 per maand bij jaarbetaling voor 2.500 workflowuitvoeringen. Pro: €50 voor 10.000. Business: €667 voor 40.000, self-hosted. De Community Edition is self-hosted beschikbaar | Workflowtool kan triggers en retries dragen, maar je hebt eigen opslag nodig voor snapshots en vrijgave | De n8n-prijspagina toont deze bedragen en rekent per volledige workflowuitvoering, niet per stap | Meerdere API's met stabiele regels en een technische beheerder |
| Make | Make rekent met credits. Elke moduleactie, zoals lezen, zoeken, aanmaken of bijwerken, verbruikt meestal één credit. Bij lege credits stoppen scenario’s en worden webhooks beperkt door queue-opslag | Goed voor orkestratie, maar de eigen versieledger en read-back moeten buiten de scenariohistorie staan | De actuele Make-documentatie beschrijft het creditmodel en de webhookqueue; controleer de planprijs in de calculator | Kleine tot middelgrote flows met voorspelbare regels |
| Eigen service met PostgreSQL | Eigen tabel voor snapshots, ledger, queue, bronversie, status en vrijgave. PostgreSQL documenteert actuele transacties en isolatieniveaus voor versie 18 | Volledige controle over compare-and-swap, idempotentie, read-back en auditrecord | Geen vaste SaaS-prijs. Reken infrastructuur, bouw en onderhoud apart | Meerdere schrijvers, hoge foutkosten, geld, voorraad of verplichte menselijke vrijgave |
Een native koppeling is prima als hij werkelijk kan bewijzen wat je nodig hebt. Een bekende appnaam is geen bewijs dat de connector stale writes blokkeert. Een workflowlaag is sterk wanneer de regels stabiel blijven en je de duurzame registratie zelf beheert. Maatwerk verdient zijn plek zodra de uitzonderingen geen randgevallen meer zijn, maar de normale manier waarop je bedrijf risico beheerst.
Een synchronisatie is pas klaar wanneer je drie vragen met bewijs kunt beantwoorden: welke bronversie gebruikte je, wat schreef je precies en wat las je daarna terug? Kan je systeem dat niet, dan verplaatst het data. Het beheerst de werkelijkheid nog niet.
Veelgestelde vragen
Veilige data-sync bouwen
Ik ontwerp met je de bronmatrix, versiecontrole en uitzonderingsqueue, en realiseer de keten van ontwerp tot livegang op je bestaande systemen. Daarbij denk ik ook mee over het vrijgaveproces en het bewijs dat je na een incident nodig hebt.
Dit artikel is geproduceerd samen met het Agent Team. Meer over de redactie.
