The webhooks versus polling decision is not simply “real-time versus slow.” It is a reliability choice about who detects change, how delivery failures are recovered, and what evidence both systems retain. Webhooks can notify quickly but may be duplicated, delayed, or lost. Polling can recover missed state but creates repeated requests and must define a safe cursor.
Reliable integrations often use both: webhooks for prompt notification and polling or reconciliation for repair. The correct design starts with the business event and consistency requirement, not a blanket preference.
Define the state you need
Ask whether you need every event or only the latest resource state. A payment ledger may need each attempt, refund, and reversal. A shipment dashboard may be able to fetch the current status after a change notice. Event history and current state are different contracts.
Define acceptable delay, volume, ordering needs, retention, and what happens if one side is unavailable for hours. These requirements determine whether a callback, incremental poll, scheduled reconciliation, or combination is appropriate.
What webhooks actually guarantee
Most webhook providers aim for at-least-once delivery: they retry until your endpoint acknowledges, so duplicates are normal. Some provide no strict ordering across event types. A successful HTTP response proves your endpoint accepted the request, not that downstream business processing finished.
Read the provider’s current documentation for retry schedule, timeout, signature scheme, event identifiers, replay tools, and retention. Never infer guarantees from the word “webhook.”
Secure the ingress boundary
Require HTTPS and verify the signature exactly as documented, usually against the raw request body and a timestamp. Parse only after verification. Enforce a reasonable timestamp tolerance and retain event identifiers to limit replay. Store secrets in managed configuration and rotate them with an overlap procedure.
Network allowlists can add a layer when provider addresses are stable, but they do not replace cryptographic verification. Do not log signatures, secrets, or sensitive full payloads.
Acknowledge quickly, process durably
The webhook endpoint should validate basic authenticity, record the event in a durable inbox, enqueue work, and return the expected success response within the provider timeout. Calling several internal services before acknowledging increases retries and ties availability together.
Use a database transaction or equivalent atomic design so the system does not acknowledge an event that it failed to retain. A durable queue lets workers retry on your schedule and exposes backlog.
Make processing idempotent
Use the provider event identifier where available, plus a domain idempotency key for operations that could arrive through more than one event. Insert the inbox record with a unique constraint. If a worker retries after partial failure, the domain transition must remain safe.
Idempotency is not “ignore every duplicate payload.” The same resource may legitimately change several times. Deduplicate by stable event or operation identity, then apply a state transition with version or status rules.
Handle ordering explicitly
An “updated” event may arrive before “created,” or a delayed failure may arrive after success. If events carry a resource version or effective timestamp, compare it with the state you have. If correctness requires full history, retain and sequence events. If current state is enough, use the webhook as a signal and fetch the authoritative resource.
Do not depend on queue arrival order unless the entire path guarantees it. Partitioning by resource can help, but reconciliation is still needed for gaps.
Design retries by failure type
Retry transient network and service failures with exponential backoff and jitter. Do not endlessly retry invalid signatures, malformed payloads, or permanently missing references. Classify failures, cap attempts, and move unresolved events to a review queue with context.
Provide an authorized replay action that reuses the same idempotent handler. Record who replayed what and why. Manual database changes are not a recovery strategy.
When polling is the better primary mechanism
Polling fits providers that do not offer events, sources where periodic freshness is sufficient, or resources that expose a reliable incremental cursor. It can also simplify low-volume integrations where a scheduled fetch has an acceptable cost and clear rate limits.
Use conditional requests, updated-since filters, pagination, and cursors when supported. Store the cursor only after the page is processed safely. Add overlap to time-based polling if timestamps can tie or arrive late, then deduplicate records.
Avoid the polling traps
Polling every resource individually creates an N+1 integration and can exceed rate limits. Fetch changed collections or batched statuses. Coordinate workers so two schedulers do not process the same cursor. Back off on provider errors and respect retry headers.
Watch for clock skew, inclusive versus exclusive timestamps, pagination changes during traversal, deletions, and records updated between pages. A full periodic comparison may be necessary if the provider’s incremental contract cannot reveal every change.
Use the hybrid pattern for resilience
Receive webhooks for low-latency change notification, then run a scheduled incremental poll or reconciliation to find missing events and verify final state. The webhook can enqueue a targeted fetch rather than carry the entire trusted business object.
This pattern costs more requests than webhooks alone but gives an explicit repair path. Choose reconciliation frequency based on business impact and provider limits, not an arbitrary universal interval.
Model an integration inbox
An inbox record can include provider, tenant, external event ID, type, received time, signature result, payload reference, processing state, attempts, last error category, and related domain object. Encrypt or minimize stored payloads according to sensitivity and retention needs.
States such as received, processing, applied, ignored-with-reason, retrying, and needs-review give operations a truthful view. Keep the raw event immutable; store processing outcomes separately.
Observe both transport and business outcomes
Transport metrics include accepted requests, signature failures, queue latency, retries, and dead letters. Business metrics include invoices updated, shipments reconciled, unknown references, amount mismatches, and state conflicts. A 200 response rate can look perfect while no order changes.
Alert on sustained backlog, old unprocessed events, reconciliation gaps, and authentication failures. Include correlation identifiers in structured logs without personal or secret data.
Test beyond the happy callback
Create fixtures for valid and invalid signatures, old timestamps, duplicate IDs, unknown event types, malformed payloads, delayed delivery, reversed order, worker failure after persistence, and replay. Contract-test against provider samples and sandbox events, but keep local deterministic tests.
For polling, test cursor restart, overlapping windows, pagination, rate limits, partial page failure, deletion, and the same update returned twice. Simulate a provider outage and confirm recovery does not flood the API.
Version payloads and handlers
Providers add fields and sometimes introduce event versions. Ignore unknown fields safely, validate required ones, and route known versions to compatible handlers. Store enough metadata to replay an old event after your code changes.
Your outgoing webhooks need the same discipline: documented schemas, stable event IDs, signatures, retry policy, delivery logs, and a customer replay path. Reliability is reciprocal.
Choose per integration, not per company
Payments may need immediate events plus daily reconciliation. Catalog imports may need incremental polling. A low-risk report may run nightly. Document the choice, guarantees, fallback, and owner for each boundary.
Our integration engineering service implements these patterns, while automated customer notifications shows how reliable internal events feed outbound communication without coupling the business flow to a channel.
Final design rule: notification plus proof
Treat a webhook as notification that something may have changed, and design a way to prove or reconcile the resulting state. Treat polling as a recovery-capable scan, and design a cursor that can restart without skipping or duplicating business effects. If you can explain acknowledgement, idempotency, ordering, retries, and repair on one page, the integration is ready to build. Send the integration brief with the provider contract and failure expectations.

