Key takeaways
- A webhook is the source system calling your endpoint when something happens, and polling is your system asking the source on a schedule whether anything changed.
- Webhooks are faster and cheaper on API quota, but delivery can fail, so a receiver can silently miss events.
- A production webhook receiver needs signature verification, a fast 2xx response, duplicate detection and no dependence on event order.
- The sturdy pattern is webhooks plus a periodic reconciliation poll, which Shopify recommends explicitly in its webhook best practices.
- Silent gaps cost the most, so an integration should report when it last confirmed that both systems agree.
Every integration between two business systems has to answer one question: how does system B find out that something changed in system A? A new order lands in the store, a payment settles, a deal closes in the CRM. If B learns about it late, the warehouse ships late. If B never learns about it, nobody notices until a customer calls.
Webhooks vs polling: which should you use?
Use webhooks when speed matters and the source system supports them. Use polling when it does not, when you cannot expose a public endpoint, or when a delay of minutes is fine. Use both when the data is money, stock or customer commitments.
| Webhooks | Polling | Webhooks plus reconciliation poll | |
|---|---|---|---|
| Who starts the exchange | The source system | Your system | Both |
| Latency | Seconds | Up to one polling interval | Seconds, with a bounded worst case |
| API quota use | Low, one call per event | High, one call per check even when nothing changed | Low, plus a few scheduled checks |
| Reliability | Delivery can fail, and some events never arrive | Reliable if the query is written well, but slow | Highest of the three |
| What the receiver must do | Expose a public HTTPS endpoint, verify signatures, answer fast, remove duplicates | Remember where it stopped and respect rate limits | Both sets of work |
| Firewall needs | Inbound access from the sender | Outbound only | Inbound plus outbound |
| Best fit | Payments, orders, ticket updates, anything time-sensitive | Systems with no webhooks, nightly syncs, internal systems behind a firewall | ERP, CRM and ecommerce integrations where a missed record costs money |
How do webhooks and polling work?
Webhooks
A webhook is an HTTP request that the source system sends to an address you control when a defined event happens. You register the address once, and from then on the source calls you. The sequence is the same across platforms:
- You register an HTTPS endpoint with the source system and choose which event types you want, such as an order being created.
- The source system gives you a secret that is used to sign every request.
- When the event happens, the source sends a POST request with a JSON body describing it.
- Your endpoint verifies the signature, stores the event, and replies with a 2xx status code.
- If the reply does not arrive in time or is not a success, the source marks the delivery as failed and may try again.
Step 5 is where most business problems begin. Stripe states that registered endpoints must be publicly accessible HTTPS URLs, so the receiver has to be reachable from the internet, which matters if your ERP lives inside a corporate network.
Polling
Polling means your system calls the source system's API on a schedule and asks what has changed. A good poll sends a bookmark, such as "everything updated since 2:15 PM," and stores the new bookmark only after the results are safely processed.
Polling is dull and dependable. It needs no public endpoint, because every connection starts from your side, and a failed run is simply retried at the next interval. Its costs are delay and quota. If you poll every 10 minutes, an event can wait nearly 10 minutes before you see it, and every poll counts against the source system's API limits whether or not anything changed. Shorter intervals shrink the delay and multiply the calls.
When should you use polling instead of webhooks?
Polling is the right choice in four cases:
- The source offers no webhooks. Many older ERPs, on-premises accounting packages and partner portals expose only a query API or a file export.
- The receiver cannot be reached from outside. An internal system with no public address can make outbound calls but cannot accept inbound ones.
- A delay of minutes or hours does not matter. Nightly stock levels, monthly reporting extracts and slowly changing reference data do not need a push.
- You need a complete view, not a stream of changes. Reconciling two systems, or loading history for the first time, is a query by nature.
If none of those apply and the data is time-sensitive, webhooks are the better primary path.
What happens when a webhook delivery fails?
The sender retries for a while and then gives up, and the retry rules differ by platform. A receiver that goes down for longer than the retry window loses events permanently unless something else recovers them.
Real platforms show the range:
| Platform | Retry behavior | Response time allowed | Source |
|---|---|---|---|
| Stripe | Retries in live mode for up to three days with exponential backoff; sandbox deliveries retry three times over a few hours | Must return a 2xx before any complex logic | Stripe webhooks |
| Shopify | Retries 8 times over 4 hours, then deletes an Admin API subscription after 8 consecutive failures | A one-second connection timeout and a five-second timeout for the whole request | Shopify HTTPS delivery |
| GitHub | Does not automatically redeliver failed deliveries; you redeliver them by hand or by script | A 2XX within 10 seconds | GitHub best practices and failed deliveries |
Shopify is blunt about the consequence. Its best-practices page says webhook delivery is not always assured, and that an app can also miss events because of handler failures or downtime. Its recommendation is to run reconciliation jobs that periodically fetch data so the app stays consistent with Shopify's data. GitHub's guidance is the same in spirit: if your server goes down, redeliver the missed webhooks once it is back.
Illustrative example: Consider a wholesaler whose online store sends an order-created webhook to a small service that writes the order into the ERP. A deploy on a Friday evening breaks the service, and it returns errors for six hours. Using Shopify's published behavior of 8 retries over 4 hours, the final retry for the earliest orders lands while the service is still down, so those orders are never delivered. Shopify also deletes an Admin API subscription after 8 consecutive failures, so later orders stop arriving until someone recreates it. Shopify emails the app's developer contact, and if nobody watches that mailbox, nobody acts, because the store shows the orders as placed and the ERP simply has fewer. The gap surfaces Monday, when a customer asks where a shipment is. A reconciliation job that fetches every order updated since its last successful run would have found the missing orders within the hour.
What must a production webhook receiver do?
A receiver that only parses JSON and writes to a database will work in a demo and fail in production. Five behaviors separate the two.
Verify the signature
Anyone who learns your endpoint address can send it a fake event. Stripe notes that without verification, an attacker could trigger actions like fulfilling orders or granting account access. Stripe signs each event with an HMAC (a keyed hash that proves the sender holds the shared secret) using SHA-256, includes a timestamp in the signed content so old captures cannot be replayed, and recommends rejecting requests outside a tolerance, with its libraries defaulting to five minutes. Stripe also requires the raw, unmodified request body for the check, so a framework that reformats the JSON first will break verification. Shopify uses an HMAC header too, and GitHub recommends a webhook secret to confirm that deliveries were sent by GitHub and not tampered with.
Answer fast, work later
The sender is waiting on your reply. Stripe says to return the 2xx before complex logic that might time out, and to process events through an asynchronous queue so that a spike, such as every subscription renewing on the first of the month, does not overwhelm the endpoint. In practice the receiver verifies, writes the raw event to a queue or table, replies 200, and a separate worker does the business logic.
Expect duplicates
The same event can arrive more than once. Stripe advises logging the event IDs you have processed and skipping repeats, and Shopify advises ignoring duplicates using the X-Shopify-Webhook-Id header. GitHub adds a wrinkle: a redelivery carries the same X-GitHub-Delivery value as the original, so that ID identifies the event but cannot tell a retry from a first attempt. The business consequence is concrete. Without duplicate handling, a repeated payment event can send two confirmations or create two invoices.
Do not depend on order
Stripe says it doesn't guarantee delivery of events in the order they were generated, and Shopify says it doesn't guarantee ordering within a topic or across topics for the same resource. Design the handler so that an invoice-paid event arriving before the invoice-created event still works, usually by fetching the current state of the object from the API instead of trusting the sequence of messages.
Keep a record
Store every raw event, the signature result, and the processing outcome. When someone asks why an order is missing, that log is the only way to answer.
Why is the sturdy pattern webhooks plus a reconciliation poll?
Webhooks give you speed and polling gives you completeness, so the two cover each other's weakness. The webhook path handles nearly everything within seconds. A scheduled job then asks the source system for every record changed since the last successful run and compares it to what the destination holds. Anything missing or stale gets repaired through the same code path that handles webhooks, so there is one set of business rules, not two.
Shopify spells out the pattern: filter by updated time and build a job that fetches all objects updated since the last time it ran. Stripe offers the same safety net for its own events. After an outage you can list events through the API, filter to those that failed delivery, and process them, though Stripe returns only events created in the last 30 days. For the rare case where Stripe fails to generate an event at all, its documentation says to poll the relevant API for the current state of the affected resource.
Three rules make the reconciliation job trustworthy:
- Use a wide overlap. Ask for changes since a point slightly before the last successful run, so a record updated during the previous run is not skipped.
- Make processing idempotent. Idempotent means that handling the same record twice produces the same result as handling it once. The reconciliation job will repeatedly meet events the webhook already handled.
- Report the outcome. Log how many records were checked and how many were repaired, and alert when repairs rise.
What does a missed event cost a business?
A missed event rarely breaks anything loudly. It leaves the two systems disagreeing, and the people relying on them find out late. An order that never reached the ERP is not picked, so the customer waits. A payment that never reached the accounting system sits unreconciled until month-end close. A stock change that never reached the storefront lets you sell goods you no longer have.
The cost scales with how long the gap stays hidden. That is the argument for reconciliation and for monitoring that measures agreement between systems, not only whether the service is running. For more on keeping an integration honest after launch, see monitoring AI in production, which applies the same discipline to automated workflows.
How should a 20 to 200 person company choose?
Work through these questions for each data flow, not for the whole company.
- Does the source system offer webhooks? If not, poll.
- Can the destination accept inbound HTTPS from the internet, or sit behind a cloud receiver? If not, poll.
- How long can the business tolerate a delay? Over an hour, polling alone is usually enough. Under a few minutes, add webhooks.
- What does a missed record cost? If it touches revenue, stock, compliance or a customer promise, add the reconciliation poll.
- Who owns the alert? Name the person who gets paged when the last confirmed sync is older than the agreed limit.
Most integrations that connect an ERP, a CRM and a storefront end up with webhooks for orders and payments, polling for slowly changing reference data, and a nightly reconciliation across both. Our guide to connecting AI to ERP and CRM data covers the wider question of how those systems feed automation and AI.
How Kastling approaches this
Integration work at Kastling would start with the business process, not the transport. The team would map which events matter, what each missed event would cost, and who owns the fix, then connect the systems already in place instead of replacing them. For each flow it would choose between webhooks, polling or both, agree how the business will know the two systems still match, and test the design against real scenarios, including a deliberate outage. This sits within AI Integration & Automation, and cloud receivers and queues are built on AWS or Azure, with specialists brought in where needed.
Questions
Can we use webhooks if our ERP sits behind a firewall?
Not directly, because the sender must reach a public HTTPS address. The usual fix is a small receiver in the cloud that accepts the webhook and places it on a queue, and your internal systems pull from that queue over an outbound connection. If the ERP itself must be the receiver, a polling job inside the network is simpler and has no inbound firewall rule to maintain.
How often should a reconciliation poll run?
Set the interval from the cost of a gap, not from technical habit. Orders and payments often justify every 15 to 60 minutes, and slower-moving records such as customer profiles can reconcile nightly. The job should ask for everything changed since its last successful run, so a missed run delays the fix rather than losing data.
Is there a third option besides webhooks and polling?
Yes. Some platforms push events into a message broker or an event bus that you subscribe to, and some databases stream their changes out. Stripe, for example, can send events directly to Amazon EventBridge or Azure Event Grid. Those options add infrastructure to run, so they usually come after the simple webhook-plus-reconcile design has proven too limited.
What should we monitor on a webhook integration?
Track four things: the time since the last event arrived, the count of rejected signatures, the depth of the processing queue, and the result of each reconciliation run, including how many records it had to repair. A reconciliation run that repairs records is not a failure. It is the safety net working, and a rising repair count is the early warning that deliveries are failing.