Definition
Webhook and polling are the two classic models for informing a client of a server-side state change (a payment settled, a transfer received, a document signed).
- Webhook (push): the server sends an HTTP request to the client as soon as an event occurs.
- Polling (pull): the client queries the server periodically to see whether there is anything new.
The choice is a defining one for any fintech API integration, with major implications for latency, reliability, complexity and cost.
The webhook model
Low latency, minimal load (one message per event), but complexity on the client side (a public endpoint, signing, retries, idempotency) and an endpoint that must stay available 24/7.
The polling model
Medium latency (N seconds), high load (N requests per minute per resource), but low client complexity (a simple GET) and no endpoint to expose.
Detailed comparison
| Aspect | Webhook | Polling |
|---|---|---|
| Latency | < 1 s | N s (5-60 s) |
| Server load | Low (event-driven) | High |
| Client complexity | Medium (endpoint, signing, retries) | Low (GET) |
| Public endpoint | Required | No |
| Firewall / NAT | Complicated | Simple |
| Mobile | Difficult | Natural |
| Exactly-once | Difficult (idempotency required) | Easy |
| Debug | Difficult | Easy (replay GET) |
Fintech use cases
- Webhook (preferred): Stripe, Adyen, Mollie (payment notifications), Bridge, Tink, TrueLayer (PIS), DocuSign, Yousign (signing), Sumsub, Onfido (KYC).
- Polling: mobile apps with no backend, or an urgent and frequent event (blockchain status) — rare in production.
Webhook best practices
- Security: always verify the signature (HMAC or RFC 9421), HTTPS, IP allowlisting, timestamp verification (anti-replay).
- Reliability: exponential retries on the server side, an idempotency key on the client side (process each event only once), a fast 2xx ACK (otherwise queue asynchronously), order not guaranteed.
- Observability: log every webhook, monitor the error rate and the ACK latency, alert on retries (tools: Hookdeck, Svix).
Polling best practices
Exponential backoff (don't hammer every second), ETag / If-None-Match (304 if nothing changes), long polling (the server holds the connection for up to 30 s) and cursor-based pagination from the last checkpoint.
Webhook + polling = the best of both
Many fintechs offer both: the webhook as the main channel, polling as a fallback, and periodic reconciliation (GET) to make sure no event was missed. Stripe, Bridge and Adyen recommend this hybrid pattern.
Modern alternatives
Server-Sent Events (one-way push), WebSockets (full-duplex, intensive real-time), gRPC streaming, and MQTT/AMQP/Kafka for very high volume. Webhooks remain dominant in fintech because they are simple, REST-compatible and universally supported.
What webhook / polling is not
- Not a protocol: they are patterns over HTTP, not formal standards.
- A webhook is not a callback: a callback is inline within a request, a webhook is a standalone call.
- Polling is not retry: polling is regular, retry occurs on failure.
- Not a guarantee of exactly-once in itself: you need webhook + idempotency + a checkpoint in the database.
Within the PSD2 / Open Finance ecosystem
- PIS: the Berlin Group offers a
notification_url(webhook) to signal the completion of a payment. - AIS: few webhooks (ASPSPs rarely push), hence a rather polling-based model for refreshing.
- PSD3 / FIDA: should standardise webhooks (consent, data sharing).
- VoP: synchronous (request/response).
- Wero / SCT Inst: a mobile push notification, close to the webhook model on the app side.
Real-world examples
- Stripe: webhooks for ~200 event types (
payment_intent.succeeded,charge.refunded), with a configuration and simulation dashboard. - Bridge:
payment.completed,account.refreshedandconsent.expiringwebhooks, signed with HMAC SHA-256. - Sumsub: an
applicantReviewedwebhook at the end of KYC. - Tools: ngrok and RequestBin for local testing, Svix and Hookdeck in production.
- Cost: a naive player polling 100k customers every 30 s generates 3.3m requests/hour — migrating to webhooks cuts the cost by ~99%.
- Failed exactly-once: crediting a customer on every webhook with no idempotency leads, after a retry, to a double credit — always deduplicate by
event_id.