Webhooks vs Polling: When to Push, When to Pull
Every integration eventually confronts the same question: how does my system learn that something changed in someone else’s system? The two answers are polling and webhooks. Polling asks the question repeatedly. Webhooks get notified when the answer changes. Understanding which approach fits a given situation — and why — shapes everything from latency and cost to reliability and operational complexity.
Polling: The Default That Mostly Works
Polling is the simpler mental model. Your application sends requests to an API on a schedule — every 30 seconds, every minute, every hour — and checks whether anything has changed since the last check. If yes, process the changes. If no, wait for the next interval.
The implementation is mechanical. You need a scheduler (cron, a background job system, whatever your stack uses), the API call itself, logic to track state between runs (usually a timestamp or cursor representing the last-processed point), and handling for the delta between what you last saw and what the API now returns.
Polling works reliably because it puts your system in control. You initiate every request. You define the schedule. Your system’s behavior is not dependent on someone else’s ability to deliver a notification. If the API is unavailable when you poll, you retry on the next interval. Nothing is lost; you just detect the change later than you would have otherwise.
The costs are real. Polling at any meaningful frequency means most requests return nothing — you are asking “did anything change?” and the answer is usually no. At high frequency, this generates significant load on the API you are polling (which is why many APIs rate-limit polling behavior more aggressively than other endpoints) and wastes compute in your own infrastructure. Polling at low frequency reduces waste but increases latency — the time between when something changes and when you learn about it.
Polling makes most sense when your use case tolerates latency on the order of the polling interval, when the API you are integrating does not support webhooks, or when the reliability of receiving every event matters more than receiving it immediately.
Webhooks: Inversion of Control
Webhooks flip the model. Instead of your system asking the API if something changed, the API tells your system when something changes. You register an HTTP endpoint with the API provider. When a relevant event occurs — a payment succeeds, a file is uploaded, a user account is created — the provider sends an HTTP POST to your endpoint with a payload describing the event.
The latency is fundamentally different. Webhook delivery is typically measured in seconds, sometimes milliseconds. The moment an event occurs on the provider’s side, your system can know about it. For use cases where timeliness matters — payment confirmation, fraud alerts, workflow triggers — this is the only practical option.
The operational model is also different, and this is where most integrations go wrong. With polling, you are the caller. You control timing and retry behavior. With webhooks, you are the receiver. The provider calls you, and if your endpoint is unavailable when they call, you depend on the provider’s retry policy to eventually deliver the event. If your endpoint is down for an hour and the provider retries for 30 minutes, you lose events.
Receiving webhooks reliably requires your endpoint to be publicly accessible, always available (or at least highly available), and capable of responding quickly. The convention is to return an HTTP 200 immediately upon receipt and process the event asynchronously in a background queue — acknowledging delivery first, doing work second. An endpoint that takes 30 seconds to process and respond risks the provider treating the delivery as failed and retrying.
Security: The Piece Most Tutorials Skip
Webhook endpoints are publicly accessible HTTP endpoints. Anyone who discovers your endpoint URL can send POST requests to it. Without verification, a malicious actor could send fabricated events to trigger actions in your system.
The standard solution is signature verification. The provider signs the webhook payload using a shared secret (a key unique to your integration). Before processing any webhook, your endpoint recomputes the expected signature and compares it to the one in the request header. If they do not match, reject the request.
The exact mechanism varies by provider — Stripe uses HMAC-SHA256 with a timestamp embedded to prevent replay attacks; GitHub uses the same algorithm with a slightly different structure — but the concept is universal. Always verify webhook signatures before trusting the payload. Every major webhook provider documents exactly how to do this, and most publish official libraries that handle it for you.
Also validate the timestamp if the provider includes one. A request with a valid signature but a timestamp 20 minutes in the past is likely a replay of a previously captured request. Reject anything outside a reasonable window (five minutes is standard).
Idempotency: Because Events Arrive Twice
Providers cannot guarantee exactly-once delivery. Network failures, timeouts, and infrastructure restarts mean webhook deliveries can be duplicated. Your endpoint may receive the same event twice, with the same event ID. If processing that event triggers a payment, sends an email, or modifies a record, receiving it twice must not result in two payments, two emails, or a corrupted record.
The solution is idempotency: check whether you have already processed an event before processing it. Store event IDs and skip any event whose ID you have already seen. This is not optional for production webhooks — duplicate delivery is a given, and the burden of handling it is on the receiver.
Choosing
The practical heuristic: if the API supports webhooks and your infrastructure can run a publicly accessible receiver, use webhooks for anything where latency matters or where polling would generate high API call volume. Use polling where webhook support is absent, where your receiver cannot be reliably public-facing, or where you need to re-process historical events on a schedule regardless of whether anything changed.
For sophisticated integrations, use both. Webhooks for real-time notification, periodic polling as a reconciliation mechanism to catch any events that webhook delivery missed. The combination gives you both timeliness and reliability.
Polling is simpler to implement and easier to reason about. Webhooks are faster and more efficient but introduce receiver availability and event ordering as concerns you must handle. Neither is superior in the abstract. Choose based on what your integration actually needs.