API design
Polling vs webhooks
Short answer
Use webhooks when changes are frequent enough that push delivery saves meaningful latency and the receiver can run a secure endpoint. Use polling when the consumer cannot accept inbound traffic, the source offers no reliable push, or simplicity and replay control matter more than immediacy.
Written and reviewed by Sahil Srivastav
What each one actually is
Polling asks the source for current state or changes on a schedule. It works through ordinary outbound connections and can recover by querying from a cursor, but empty requests consume capacity and short intervals trade cost for freshness.
A webhook sends an event to a consumer endpoint when the source observes a change. It reduces idle traffic and latency, but delivery is at-least-once in most systems and requires authentication, retries, deduplication, and a replay path.
Both patterns need cursor or event identity, backoff, and reconciliation. A webhook should notify a consumer to fetch authoritative state rather than carrying an unverified complete truth.
Side by side
| Polling | Webhooks | |
|---|---|---|
| Latency | Bounded by polling interval | Usually near event time |
| Network direction | Consumer opens outbound requests | Provider calls consumer endpoint |
| Idle traffic | Can be high | Low between events |
| Receiver requirements | No inbound endpoint | Public or reachable secure endpoint |
| Delivery failure | Retry next poll | Provider retry queue and dead letter needed |
| Duplicate handling | Repeated snapshots or cursor retries | Duplicate event deliveries are normal |
| Ordering | Consumer can read ordered changes | Network and retry timing may reorder |
| Recovery | Re-read from cursor or timestamp | Replay endpoint or reconciliation query |
Choose Polling when
- The consumer is behind a firewall or cannot expose an endpoint
- The provider has no trustworthy event delivery
- A periodic freshness window is acceptable
- The consumer needs to recover from a durable cursor and query authoritative state
Choose Webhooks when
- Low latency matters and changes are relatively sparse
- The consumer can authenticate and handle inbound requests
- The provider can sign, retry, and replay events
- The integration needs to avoid empty requests at scale
The trade-off in detail
Webhooks shift work from the provider’s read path to delivery operations. Persist attempts, sign the payload, set a timeout, retry with backoff, and stop retrying into a dead endpoint; otherwise one customer can consume the sender’s workers.
Polling looks wasteful but is often easier to reason about during repair. A cursor lets a consumer catch up after downtime, while webhook systems still need a reconciliation job because delivery can be lost or permanently rejected.
Do not perform large business work in the webhook request. Authenticate, record the event id, acknowledge quickly, and process asynchronously with idempotency.
Things that are commonly said and are wrong
- “Webhooks guarantee delivery.” They provide a delivery attempt; durable retries and replay are separate features.
- “Polling always overloads the API.” Conditional requests, cursors, backoff, and sensible intervals can make polling cheap.
- “A webhook payload is current truth.” Fetch current state when events can be reordered or coalesced.
FAQ
Which is cheaper?
Webhooks usually reduce idle request volume, but delivery infrastructure and retries add cost. Polling can be cheaper at small scale or when responses are cacheable and the freshness window is broad.
How should webhook retries work?
Use exponential backoff with a cap, an attempt limit or dead-letter state, signed payloads, and an operator replay path. Consumers must deduplicate by stable event ID.
Can I use both?
Yes. Use webhooks for prompt notification and periodic polling for reconciliation. The poll should compare a cursor or version, not blindly replay every object.