REST Webhooks vs Polling
Choosing between webhooks and polling for event delivery in REST APIs: trade-offs in latency, reliability, security, and operations, with a working example of both.
What you'll learn
- ✓When polling is the right answer
- ✓How webhooks deliver and retry
- ✓Security: signing and verifying payloads
- ✓Idempotent consumers and dedupe
- ✓Operational gotchas on both sides
Prerequisites
- •Basic HTTP and REST knowledge
If your API has events worth telling consumers about, you eventually have to choose: do they ask, or do you tell? Polling and webhooks both work; they fail in different ways. Picking the right one early saves you from a painful migration later.
What and Why
Polling is the client periodically calling your API to ask what changed. Webhooks are your server calling the client’s URL when something changes. Polling is pull, webhooks are push.
Polling is dead simple: it reuses your normal REST surface, has no new auth model, and the client is always in control. Its weakness is latency and waste; most polls return nothing. Webhooks deliver near real-time but force you to operate an outbound HTTP system with retries, signing, queues, and dead letters. The provider takes on more work so the consumer can stay reactive.
Mental Model
Picture two diners. A poller walks to the kitchen every five minutes asking if the food is ready. A webhook consumer sits at the table and the waiter brings the plate the moment it is up. The first model is simple but tiring; the second model is faster but requires a working waiter, a known table, and a plan for when the diner is in the bathroom when the food arrives.
Hands-on Example
Polling looks like a paginated changes feed. The client stores a cursor and asks for everything since it.
GET /v1/changes?since=2026-06-28T10:00:00Z&limit=100
{
"events": [
{ "id": "ev_01", "type": "order.paid", "at": "2026-06-28T10:00:05Z" },
{ "id": "ev_02", "type": "order.shipped","at": "2026-06-28T10:01:11Z" }
],
"next_cursor": "2026-06-28T10:01:11Z"
}
Webhooks reverse it. The consumer registers a URL and gets POSTs.
POST https://consumer.example.com/hooks/orders
Webhook-Id: ev_01
Webhook-Timestamp: 1719568805
Webhook-Signature: t=1719568805,v1=8a4f...
{ "type": "order.paid", "id": "ev_01", "data": { "order_id": "o_42" } }
The consumer verifies the signature, dedupes by Webhook-Id, and responds 2xx quickly.
Polling:
client --GET /changes?since=cursor--> server
client <--events[]-- server
(repeat every N seconds)
Webhooks:
event happens
-> [ outbox / queue ] -> POST consumer URL
|
2xx -> done
non-2xx / timeout -> retry with backoff
exhausted -> dead letter + alert A real webhook system is not just “POST when something happens.” It is a queue, a worker, exponential backoff, a dead-letter table, and a replay endpoint so consumers can recover after an outage.
Common Pitfalls
- Polling too aggressively. A client polling every second across thousands of tenants will dwarf your real traffic. Cache aggressively and return
304 Not Modifiedwhen nothing changed. - Polling too slowly. Hourly polls make events feel broken. Match the cadence to the business need, not the developer’s comfort.
- Webhooks without signing. An unsigned endpoint is a free hand to anyone who guesses the URL. Always HMAC the body with a shared secret and a timestamp.
- Treating the consumer as reliable. It will be down, slow, or rate-limited. Retry with jitter, cap attempts, and dead-letter for human review.
- No replay path. When a consumer misses a day of events, “we already sent them” is not an answer. Offer a
/changes?since=feed even if you push.
Practical Tips
Send minimal payloads with a stable event_id and a link to fetch the full object. That way you do not leak data via stale snapshots, and consumers can verify state. Require a 2xx within a few seconds; anything slower will time out under load. Document your retry schedule so consumers know how long they have to recover. For internal services, a queue like SQS or Kafka beats both webhooks and polling, but only because you control both ends.
If you can only build one, build the polling feed first. It is the source of truth and the recovery mechanism that webhooks rely on anyway.
Wrap-up
Polling trades latency for simplicity; webhooks trade simplicity for latency. The strongest APIs ship both: a push for real-time happiness and a pull for honest recovery. Pick your default based on who feels the most pain when an event is missed, then build the other as a safety net.
Related articles
- REST APIs REST API Design Best Practices: A Practical Guide
Apply REST design best practices for resources, naming, status codes, pagination, and versioning to build clean, durable APIs.
- REST APIs REST API Error Handling Conventions
Design clear, consistent error responses for REST APIs using HTTP status codes, problem details, and error envelopes that clients can actually handle.
- REST APIs REST API HATEOAS Explained
Understand Hypermedia as the Engine of Application State, why most REST APIs skip it, and when adding hypermedia links actually pays off.
- REST APIs REST API Pagination Patterns
Compare offset, cursor, and keyset pagination for REST APIs. Pick the right pattern for your data, scale, and client experience.