API integration comparison

Webhook vs Polling

The classic push vs pull debate in API integration. Webhooks push events to you instantly; polling asks repeatedly. The right choice depends on your latency needs, infrastructure constraints, and the reliability guarantees you need.

TL;DR

  • Webhook — event-driven push. The source server calls your endpoint when something happens. Near-instant, efficient, but your endpoint must be publicly reachable.
  • Polling — scheduled pull. Your client asks "anything new?" at regular intervals. Works from anywhere, simple to implement, but wastes resources and has up-to-interval latency.
  • Default to webhooks for external integrations where the source supports them. Use polling as a fallback, for simple cases, or when you operate behind a firewall.

Side-by-side comparison

AspectWebhookPolling
DirectionPush — server calls your endpointPull — your client calls server
LatencyMilliseconds — event-drivenUp to full poll interval
Server loadLow — only calls when events occurHigher — constant requests even when nothing changed
ReliabilityDepends on retry mechanism of sourceClient controls — always gets current state on request
ImplementationExpose a public HTTPS endpointA scheduled job or loop calling an API
Firewall friendlinessRequires public endpoint (inbound)Works anywhere (outbound only)
DebuggingHarder — events arrive asynchronouslyEasier — deterministic, inspectable
Best forPayment events, CI/CD triggers, third-party SaaSSimple scripts, behind-firewall services, reconciliation

Code side-by-side

Getting notified when a GitHub PR is merged:

Webhook (Express handler)

// GitHub calls this URL on PR merge
app.post('/webhooks/github', (req, res) => {
  const sig = req.headers['x-hub-signature-256'];
  if (!verifySignature(sig, req.body)) {
    return res.status(401).send('Unauthorized');
  }
  const { action, pull_request } = req.body;
  if (action === 'closed' && pull_request.merged) {
    triggerDeploy(pull_request.head.sha);
  }
  res.status(200).send('OK');
});

Polling (cron every 60 s)

// Runs every minute — checks for merged PRs
async function pollMergedPRs() {
  const prs = await github.pulls.list({
    owner: 'acme', repo: 'app',
    state: 'closed',
    sort: 'updated',
    per_page: 10,
  });
  for (const pr of prs.data) {
    if (pr.merged_at && !seen.has(pr.id)) {
      seen.add(pr.id);
      triggerDeploy(pr.merge_commit_sha);
    }
  }
}
setInterval(pollMergedPRs, 60_000);

When to use Webhooks

  • Payment providers. Stripe, PayPal, and Adyen push payment events (succeeded, failed, refunded) seconds after they occur — too important to delay by a polling interval.
  • CI/CD triggers. GitHub, GitLab, and Bitbucket push repository events (push, PR merge) to your build system instantly via webhooks.
  • Third-party SaaS integrations. CRM, support tools, and e-commerce platforms all offer webhooks for real-time event delivery.
  • High event volume with sparse changes. If events are rare but time-sensitive, constant polling wastes resources; a webhook delivers exactly when needed.

When to use Polling

  • Behind-firewall services. Internal tools that cannot expose a public endpoint must poll outbound APIs.
  • Sources that do not support webhooks. Many older APIs, FTP-based data feeds, or database change feeds require polling.
  • Periodic reconciliation. Even with webhooks, you should periodically poll to catch any missed events and reconcile your state with the source of truth.
  • Simple scripts and one-off tasks. A cron job polling an API is far simpler to implement and operate than a webhook endpoint with signature verification and retry handling.

English phrases engineers use

Webhook conversations

  • "Register a webhook endpoint in the Stripe dashboard."
  • "Always verify the signature to reject forged requests."
  • "Make the handler idempotent — Stripe may retry on timeout."
  • "Return 200 OK immediately and process in the background."
  • "Check the webhook logs in the provider dashboard for failed deliveries."

Polling conversations

  • "We poll the API every 30 seconds for new orders."
  • "Use a since parameter (last seen timestamp) to avoid re-fetching old records."
  • "Aggressive polling is hitting our rate limits — back off to 5 minutes."
  • "We use ETag / If-None-Match so the server returns 304 when nothing changed."
  • "Polling is our fallback for webhook failures."

Quick decision tree

  • Source supports webhooks, endpoint is public → Webhook
  • Service is behind a firewall / private VPC → Polling
  • Need sub-second event latency → Webhook
  • Simple cron script, no infrastructure to expose → Polling
  • Payment / security-critical events → Webhook + periodic reconciliation polling
  • Source does not offer webhooks → Polling
  • Many events expected but changes are rare → Webhook (polling wastes resources)

Frequently asked questions

What is a webhook?

A webhook is an HTTP callback. When an event occurs in system A, it sends an HTTP POST request to a URL you configure on system B. The event is pushed to you immediately — you do not have to ask. Examples: GitHub sends a webhook when a commit is pushed; Stripe sends a webhook when a payment succeeds.

What is polling?

Polling is when your client repeatedly asks a server "has anything changed?" at regular intervals — every 5 seconds, every minute, every hour. If there is new data, you get it; if not, you get an empty response and wait until the next poll.

Which has lower latency?

Webhooks have much lower latency. You are notified within milliseconds of the event. Polling latency equals up to the full polling interval — if you poll every 60 seconds, you may wait up to 60 seconds to learn about an event. Reducing the interval improves latency but increases server load.