Webhooks vs polling: kies de juiste integratie-aanpak
Webhooks versus polling: leer hoe beide de latentie, fouten, ratelimieten en de retry- en replaypatronen beïnvloeden die data synchroon houden.

Welk probleem lossen we op als we data synchroniseren?
Synchroniseren klinkt als “updates snel laten verschijnen,” maar de echte opdracht is lastiger: zorg dat twee systemen het eens zijn over wat waar is, zelfs wanneer berichten laat, gedupliceerd of zoekraken.
Bij webhooks versus polling zit het verschil in hoe je hoort dat iets veranderd is.
Een webhook is push. Systeem A roept jouw endpoint aan wanneer er een gebeurtenis plaatsvindt (bijvoorbeeld “invoice paid”). Polling is pull. Jouw systeem vraagt systeem A op schema: “is er iets nieuw sinds de laatste keer?”
Systemen synchroon houden betekent meestal zowel events als staat bijhouden. Events vertellen wat er gebeurd is. Staat vertelt hoe het record er nu uitziet. Timing is belangrijk omdat integraties zelden in perfecte volgorde lopen. Een “updated”-event kan arriveren vóór “created”, kan twee keer komen of helemaal niet.
Het doel is correcte data, niet alleen verse data. “Correct” betekent dat je geen wijzigingen mist, dezelfde wijziging niet dubbel toepast, kunt herstellen na downtime zonder handmatige opschoning, en kunt aantonen wat je verwerkt hebt en wanneer.
Een praktisch voorbeeld: je betaalprovider stuurt een webhook zoals “payment_succeeded.” Je app maakt een order en zet die op betaald. Als je webhook-endpoint kort onbereikbaar is geweest, zie je dat event misschien nooit. Een polling-job die vraagt naar betalingen bijgewerkt “sinds gisteren” kan het gat verifiëren en de orderstatus herstellen.
De meeste echte integraties gebruiken uiteindelijk beide: webhooks voor snelheid, polling voor backfill en verificatie. De methode is minder belangrijk dan de veiligheidsvoorzieningen eromheen.
Latentie en versheid: hoe snel updates echt binnenkomen
Als mensen webhooks versus polling vergelijken, bedoelen ze vaak één ding: hoe snel merkt je app een wijziging ergens anders op. Die versheid is geen luxe; het beïnvloedt supporttickets, dubbel werk en of gebruikers vertrouwen hebben in wat ze zien.
Polling heeft ingebouwde vertraging omdat je alleen op schema vraagt. Als je elke 5 minuten polt, kan een update ergens tussen enkele seconden en bijna 5 minuten later aankomen, plus API-responstijd. Vaker pollen verbetert versheid, maar verhoogt API-calls, kosten en de kans op ratelimits.
Webhooks kunnen aanvoelen als bijna real-time omdat de provider een event pusht zodra iets gebeurt. Maar ze zijn niet instant of gegarandeerd. Providers kunnen events batchen, later opnieuw proberen of levering pauzeren. Jouw systeem voegt ook vertraging toe (wachtrijen, database-locks, deploys). Een realistischer verwachting is: snel als alles gezond is, uiteindelijk consistent als dat niet zo is.
Verkeerspatroon doet ertoe. Polling geeft een gelijkmatige, voorspelbare belasting. Webhooks zijn bursty: een druk uur kan honderden events per minuut sturen, en daarna niets. Als je webhooks accepteert, ga uit van pieken en plan om events te queueen zodat je ze gecontroleerd kunt verwerken.
Voordat je iets ontwerpt, kies een doel-venster voor versheid:
- Seconden: gebruikersmeldingen, chat, betaalstatus
- Minuten: supporttools, admin-views, lichte rapportage
- Uren: nachtelijke reconciliatie, laag-prioriteit analytics
Als een salesteam nieuwe leads binnen 1 minuut wil zien, brengen webhooks je daar. Een “veiligheidspoll” elke paar uur kan nog steeds gemiste events oppikken en de eindstaat bevestigen.
Faalwijzen die je echt in productie zult zien
De meeste integraties falen op saaie, herhaalbare manieren. De verrassing is niet dat er iets breekt. Het is dat het stilletjes breekt. Snelheid is makkelijk om over te discussiëren. Betrouwbaarheid is waar het echte werk zit.
Polling-fouten zien er vaak uit als “we hebben de update niet gezien,” zelfs als de code goed lijkt. Timeouts kunnen een request halverwege afbreken. Partiële responses glippen erdoor als je alleen kijkt naar HTTP 200 en de body niet valideert. Paginatie-wijzigingen komen veel voor: een API verandert sortering, pagina-regels of gaat van paginanummers naar cursors, en je slaat items over of leest ze dubbel. Een klassieke fout is filteren op “updated_since” met je lokale klok en vervolgens updates missen door klokafwijking of omdat de provider een ander timestamp-veld gebruikt.
Webhooks falen anders. Levering is meestal “at least once”, dus providers retryen bij netwerkfouten en je zult duplicaten zien. Als je endpoint 10 minuten down is, kan je later een stortvloed van oude events krijgen. Problemen met signature-validatie komen ook vaak voor: een secret rolt, je valideert de verkeerde raw payload, of een proxy wijzigt headers, en plots lijken geldige events ongeldig.
De gedeelde faalwijze in beide benaderingen is duplicaten en buiten-orde bezorging. Ga ervan uit dat je hetzelfde event meer dan eens ontvangt, events laat aankomen, events buiten volgorde, en payloads met ontbrekende velden.
Je krijgt bijna nooit “exactly once.” Ontwerp voor “at least once” en zorg dat verwerking veilig is. Bewaar een idempotency-key (event-ID of provider object-versie), negeer herhalingen en pas updates alleen toe als ze nieuwer zijn dan wat je al hebt. Log ook wat je ontving en wat je ermee deed, zodat je betrouwbaar kunt replayen in plaats van te gokken.
Rate limits en kosten: API-gebruik onder controle houden
Rate limits zijn waar webhooks versus polling ophoudt een theorie te zijn en een budget- en betrouwbaarheidsonderwerp wordt. Elke extra request kost tijd en geld, en kan je relatie met de provider schaden.
Polling verbrandt quota omdat je betaalt voor het checken, zelfs als er niets veranderde. Het wordt erger als limieten per gebruiker of per token gelden: 1.000 klanten die elke minuut pollen kan eruitzien als een aanval, ook al gedraagt elke klant zich “braaf.” Polling vermenigvuldigt ook calls gemakkelijk (list-endpoints, daarna details ophalen voor elk item), en zo bereik je onverwacht een plafond.
Webhooks verminderen meestal API-calls, maar creëren piekdruk. Een provider kan duizenden events ineens leveren na een outage, bulkimport of productlancering. Sommigen throttlen met 429s, sommigen retryen agressief, en sommigen droppen events als je endpoint traag is. Jouw kant heeft backpressure nodig: accepteer snel, queue werk en verwerk in een veilig tempo.
Om calls te verminderen zonder correctheid te verliezen, focus op een paar patronen die in de praktijk standhouden:
- Incremental sync met “updated since”-timestamps of change tokens
- Server-side filtering (abonneer je alleen op de eventtypes die je nodig hebt)
- Batching van reads en writes (haal details in chunks, schrijf in bulk)
- Cachen van stabiele referentiegegevens (plannen, statuslijsten, gebruikersprofielen)
- Scheiden van “real-time” en “reporting” behoeften (snelle route vs nachtelijke jobs)
Plan voor pieken voordat ze gebeuren. Houd een speciale backfill-modus die langzamer draait, quota respecteert en gepauzeerd/hersteld kan worden.
De juiste aanpak kiezen: een eenvoudige beslisgids
De keuze tussen webhooks en polling komt meestal hierop neer: heb je snelheid nodig, of heb je een eenvoudige, voorspelbare manier nodig om updates te krijgen, ook als de vendor onbetrouwbaar is?
Polling is vaak de betere default wanneer de derde partij geen webhooks biedt, of wanneer je workflow een vertraging kan verdragen. Het is ook makkelijker te beredeneren als je alleen een dagelijkse of uurlijkse sync nodig hebt en de API een duidelijk “updated since”-filter heeft.
Webhooks zijn de betere default wanneer tijd ertoe doet: “nieuwe order ontvangen”, “betaling mislukt”, “ticket toegewezen.” Ze verminderen verspilde API-calls en kunnen werk direct triggeren.
Een praktische vuistregel is beide te gebruiken als correctheid belangrijk is. Laat webhooks je snelheid geven en laat polling opruimen wat je gemist hebt. Verwerk bijvoorbeeld webhooks snel en voer daarna elke 15 minuten (of elk paar uur) een geplande poll uit om gaten te dichten door gedropte events of tijdelijke outages.
Een korte leidraad:
- Als minuten vertraging acceptabel zijn, begin met polling.
- Als updates binnen seconden moeten verschijnen, begin met webhooks.
- Als de vendor wankel is of events kritisch zijn, plan voor webhook + polling.
- Als de API sterk gelimiteerd is, geef de voorkeur aan webhooks plus lichte polling.
- Als datavolume hoog is, vermijd frequente volledige polls.
Voordat je beslist, stel de vendor een paar vragen en krijg heldere antwoorden:
- Welke eventtypes bestaan er en zijn ze compleet (create, update, delete)?
- Retryen ze webhooks en hoe lang?
- Kun je events opnieuw afspelen of een eventgeschiedenis opvragen op tijdsbereik?
- Ondertekenen ze webhook-requests zodat je authenticiteit kunt verifiëren?
- Ondersteunen ze “updated since”-queries voor efficiënte polling?
Stappenplan: ontwerp een sync die correct blijft
Een “correcte” sync is niet alleen “data verschijnt.” Het betekent dat de juiste records overeenkomen, de laatste wijziging wint, en je kunt aantonen wat er gebeurde als er iets misgaat.
Begin met een plan dat je kunt testen en monitoren:
- Definieer de bron van waarheid en de regels. Kies welk systeem elk veld beheert. Bijvoorbeeld: de CRM beheert klantnaam, maar jouw billing-tool beheert subscriptionstatus. Bepaal wat “vers genoeg” betekent (bijvoorbeeld “binnen 5 minuten”) en welke fouten acceptabel zijn.
- Kies stabiele identifiers. Bewaar de unieke ID van de derde partij naast je interne ID. Vermijd e-mail of naam als sleutel (die veranderen). Sla indien beschikbaar een versie of “updated at”-timestamp op om nieuwere data te detecteren.
- Plan de initiële import en daarna incrementele updates. Behandel de eerste import als een afzonderlijke job met checkpoints zodat je kunt hervatten. Daarna verwerk je alleen wijzigingen (events, “since”-queries of beide) en registreer je een cursor zoals “laatste succesvolle sync-tijd.”
- Behandel deletes en merges doelbewust. Bepaal of deletes records verwijderen, archiveren of inactief markeren. Bij merges kies je welke ID blijft en houd je een audittrail bij.
- Stel monitoringssignalen in. Volg sync-lag, mislukte calls en een vastgelopen queue. Alert wanneer lag je drempel overschrijdt, niet alleen wanneer iets crasht.
Wanneer je dit implementeert, houd keuzes zichtbaar in je datamodel: externe ID's, timestamps, statusvelden en een plek om sync-checkpoints op te slaan. Die structuur houdt sync correct als de echte wereld rommelig wordt.
Idempotentie en ordering: de kern van betrouwbare integraties
Als je lang genoeg webhooks versus polling-integraties bouwt, verschijnt één regel steeds: je zult duplicaten, retries en buiten-orde updates zien. Als je sync niet veilig hetzelfde bericht opnieuw kan verwerken, zal het na verloop van tijd uit elkaar drijven.
Idempotentie betekent “gelijke input, gelijk resultaat,” zelfs als het twee keer binnenkomt. Behandel elk binnenkomend event als “misschien herhaald” en ontwerp je handler veilig. Een veelgebruikt patroon: bereken een dedup-key, controleer of je het al hebt verwerkt, en pas dan wijzigingen toe.
Dedup-keys hebben trade-offs. Een event-ID is het beste als de provider er een geeft. Zo niet, kun je een objectversie gebruiken (bijvoorbeeld een oplopende revisie). Timestamp-vensters zoals “negeer herhalingen voor 10 minuten” zijn fragiel omdat late aankomsten voorkomen.
Ordering is de andere helft. Globale ordering is zeldzaam, richt je op per-object ordering. Pas updates op een enkel ticket, factuur of klant alleen toe als de versie nieuwer is dan wat je opgeslagen hebt. Als je geen versie hebt, gebruik last-write-wins met een duidelijke regel (bijvoorbeeld nieuwer updated_at wint), en accepteer dat klokafwijking nog steeds randgevallen kan veroorzaken.
Bewaar genoeg om te herstellen en te replayen zonder te gokken:
- Een per-object “last seen”-versie of updated_at
- Een laatst verwerkte cursor of checkpoint voor polling-jobs
- Een tabel met verwerkte event-IDs (met een retentieregel als het snel groeit)
- De raw payload voor een korte periode, zodat je fixes opnieuw kunt draaien
Voorbeeld: een Stripe-betalingswebhook arriveert twee keer, daarna arriveert een “paid”-update vóór het “created”-event. Als je de laatste statusversie van de factuur bewaart en oudere updates negeert, kom je uiteindelijk correct uit.
Retry- en replaypatronen die stille data-drift voorkomen
De meeste integraties falen stilletjes. Een webhook komt te laat, een polling-job raakt een limiet, of je app time-out tijdens opslaan. Zonder retries en replay lopen systemen langzaam uiteen totdat een klant klaagt.
Webhook-retries: accepteer snel, verwerk veilig
Providers retryen meestal als je niet snel genoeg een succesvolle HTTP-code teruggeeft. Behandel het webhook-request als een leveringsmelding, niet als de plek om zwaar werk te doen.
Een praktisch webhook-patroon:
- Antwoord snel met een 2xx na basale validatie (signature, schema, timestamp).
- Bewaar het event met een unieke ID en markeer het als pending.
- Verwerk asynchroon met een worker en volg pogingen.
- Bij tijdelijke fouten: later nogmaals proberen. Bij permanente fouten: stop en alert.
- Gebruik 4xx voor slechte data en 5xx alleen voor echte serverproblemen.
Dit voorkomt een veelgemaakte valkuil: denken dat “webhook ontvangen” gelijkstaat aan “data is gesynchroniseerd.”
Polling-retries: wees beleefd tegen de API
Polling faalt anders. Het risico is een thundering herd van retries na een korte outage, wat ratelimits verergert. Gebruik exponential backoff plus jitter en houd een “since”-cursor zodat je niet alles opnieuw moet scannen.
Als je iets nu niet kunt verwerken, zet het in een dead-letter queue (of tabel) met de reden. Dat geeft je een veilige plek om te inspecteren, mapregels te repareren en opnieuw te draaien zonder te raden wat verloren ging.
Replay is hoe je geneest na gemiste events. Een eenvoudige replay-strategie:
- Kies een tijdsvenster (bijvoorbeeld de laatste 24 uur) of een set getroffen records.
- Haal de huidige staat opnieuw op bij de provider.
- Pas updates idempotent toe en corrigeer mismatches.
- Leg vast wat veranderd is en waarom.
Voorbeeld: je billing-provider stuurt “invoice.paid”, maar je database stond 30 seconden gelocked. Je plaatst het event in de dead-letter queue en replayt door de factuur en betalingsstatus opnieuw op te halen en je records te updaten.
Veelgemaakte fouten en hoe ze te vermijden
De meeste sync-bugs zijn geen “groot architectuur”-probleem. Het zijn kleine aannames die leiden tot stille drift, dubbele records of gemiste updates.
Enkele die vaak terugkomen:
- Te vaak pollen zonder incrementele filters. Houd een cursor bij (updated_at, event ID, page token) en vraag alleen wijzigingen op sinds de laatste succesvolle run.
- Webhooks als gegarandeerde levering zien. Houd een backfill-job die recente geschiedenis (bijvoorbeeld de laatste 24–72 uur) opnieuw controleert en verzoent wat je miste.
- Duplicaten negeren. Maak elke write idempotent. Bewaar de provider-event-ID (of een stabiele externe ID) en weiger dezelfde wijziging twee keer toe te passen.
- Webhook-calls accepteren zonder verificatie. Valideer de signatuurtoken of verificatiemethode die de provider biedt.
- Vliegen zonder zicht op sync-gezondheid. Volg lag, backloggrootte, laatste succesvolle run en foutpercentages. Alert wanneer lag een drempel passeert.
Veel “webhooks versus polling”-debatten missen het punt: betrouwbaarheid komt van de veiligheidsriemen rond beide methoden. Een betaal-webhook kan twee keer aankomen of laat komen. Als je systeem records direct aanmaakt op webhook zonder idempotentie, kun je een klant dubbel berichten of belasten.
Korte checklist voor een gezonde integratie
Dagelijkse gezondheidscontroles lijken op elkaar, of je webhooks, polling of beide gebruikt. Je wilt weten of data vers is, of fouten zich opstapelen, en of je veilig kunt herstellen.
Een korte checklist die je in enkele minuten kunt doorlopen:
- Versheid: vergelijk “laatste event ontvangen” of “laatste poll voltooid” met je verwachte lag.
- Fouten: zoek naar retries die blijven stijgen of jobs die al een tijd niet vooruitgaan. Koppel foutcounts aan een “laatste succes”-timestamp.
- Quota's: controleer hoeveel API-calls je hebt gebruikt en wat er nog over is. Als je dicht bij de limiet zit, vertraag polling en batch requests.
- Correctheid: steekproef totalen tussen systemen (bijvoorbeeld “orders vandaag”) en controleer een paar recente records.
- Herstelbereidheid: bevestig dat je veilig een recent venster opnieuw kunt verwerken zonder duplicaten of gemiste updates.
Een nuttige gewoonte is periodiek een bekende drukke periode gecontroleerd opnieuw afspelen en bevestigen dat de resultaten overeenkomen met productie.
Voorbeeld: webhooks en polling combineren in een realistische workflow
Stel je een klein SaaS-team voor dat drie systemen synchroon moet houden: een CRM (contacten en deals), Stripe-betalingen (betalingen en refunds) en een supporttool (ticketstatus).
Ze gebruiken een webhook-first setup voor alles wat snel moet reageren. CRM-events updaten het klantrecord en triggeren interne taken. Stripe-webhooks maken facturen aan, ontgrendelen functies na betaling en markeren accounts als achterstallig bij mislukte incasso's. Voor de supporttool gebruiken ze webhooks als die beschikbaar zijn, maar houden ze ook een geplande poll omdat ticketstatussen soms in bulk veranderen.
Ze zien polling als vangnet, niet als de hoofdmotor. Elke nacht draait een reconciliatie-job die de laatste 24 uur wijzigingen uit elk systeem haalt en vergelijkt met wat de app al had opgeslagen.
Dan gebeurt er een echte outage: hun webhook-endpoint is 20 minuten down tijdens een deployment.
- CRM en Stripe retryen levering een tijdlang.
- Sommige events komen laat, sommige buiten volgorde en sommige verlopen misschien.
- De reconciliatie-poll detecteert een gat (missende event-IDs of mismatchende totalen) en vult de ontbrekende wijzigingen aan.
Wat ze loggen: inkomend event-ID, provider-timestamp, intern record-ID en het uiteindelijke resultaat (created, updated, ignored). Wat een alert triggert: herhaalde webhook-fouten, een piek in retries of reconciliatie die meer dan een kleine drempel aan ontbrekende updates vindt.
Volgende stappen: implementeer, monitor en itereer
Een praktische default voor de meeste teams is eenvoudig: gebruik webhooks voor directheid en houd een kleine polling-job voor reconciliatie. Webhooks brengen wijzigingen snel bij je. Polling pakt op wat je miste door outages, verkeerd geconfigureerde subscriptions of een provider die soms events dropt.
Maak de sync correct voordat je hem snel maakt. Behandel elke binnenkomende wijziging alsof je die veilig meer dan eens kunt toepassen.
Drie acties om als eerste te doen:
- Breng de events en velden van de provider in kaart en map ze naar je interne model, inclusief wat “delete”, “refund” of “statuswijziging” voor jou betekent.
- Ontwerp idempotentie vanaf dag één: sla een externe event-ID of versie op en maak elke update veilig om opnieuw te draaien zonder duplicaten.
- Voeg replay bewust toe: houd een “sinds laatst gezien”-cursor of tijdvenster-poll bij en bouw een admin-mogelijkheid om een bereik opnieuw uit te voeren als er iets mis lijkt.
Als het draait, is monitoring wat het draaiende houdt. Volg webhook-leveringssnelheid, fouten per reden (timeouts, 4xx, 5xx) en hoever je reconciliatie-poll achterloopt. Alert op “geen events ontvangen” en op “te veel events ontvangen.”
Als je dit liever bouwt zonder vanaf nul een volledige backend te schrijven, is AppMaster (appmaster.io) een no-code optie die je toestaat data te modelleren, webhook-endpoints te maken en retry/replay-flows te ontwerpen met visuele tools, terwijl er toch echte broncode voor deployment gegenereerd wordt.


