Skip to content

Choosing webhooks versus polling for an event registration feed

IntegrationsUpdated 2026-08-238 min read

In short

A webhook feed buys latency and gives no completeness guarantee. A scheduled poll gives completeness and cannot beat its own interval. For a registration feed the durable answer is to run both, take counts from the poll, take live movement from the webhooks, and reconcile the two every morning of show week.

It is the Tuesday of show week and the marketing lead wants the registration count refreshed through the day, because the paid campaign is being adjusted twice daily and the last-week surge is where the money moves. The nightly pull ran at 02:00. By four in the afternoon it is fourteen hours stale, and the number on the wall is wrong by roughly a day's worth of registrations.

That is a real problem and it has a real answer, but the framing of webhooks versus polling as a choice between two ways to get data is what gets teams into trouble. The two modes have different guarantees, and they fail in ways that do not overlap. A registration feed that matters usually wants both.

What each mode actually promises

A poll is a question you ask on a schedule. You control when it runs, you control what it asks for, and you can ask again. Its guarantee is that if you ask correctly, you get everything that existed at the moment you asked. Its cost is latency bounded below by your interval, and a load that grows with the size of the feed rather than with the number of changes.

A webhook is a message the vendor sends when something happens. Swapcard, for example, publishes hooks on profile creation and update, exhibitor creation and update, and planning creation and update (Swapcard, 2026), which covers most of what an organiser wants to react to. Its guarantee is speed. Its cost is that you now depend on somebody else's delivery attempt reaching your endpoint while your endpoint happens to be healthy.

Those are different properties. Latency and completeness are traded against each other, and no configuration gets you both from one mechanism.

Why is a webhook feed not a substitute for a pull?

Because the delivery contract is weaker than most teams assume, and the vendors who document it well say so directly.

Stripe states that it "doesn't guarantee the delivery of events in the order that they're generated" and tells integrators to make sure their consumer does not depend on receiving events in a specific order (Stripe, 2026). For a registration feed that means a profile update can land before the create it belongs to, and a loader that expects the create first will either error or silently drop the update.

Stripe also warns that endpoints "might occasionally receive the same event more than once" and recommends guarding against it by "logging the event IDs you've processed, and then not processing already-logged events" (Stripe, 2026). At-least-once delivery is the norm rather than an aberration, so any counter built by incrementing on receipt will overcount.

The retry window is the third property, and the one that decides your recovery design. Stripe attempts delivery "for up to three days with an exponential back off in live mode", with manual resends available for up to 15 days from the Dashboard and up to 30 days through its command line tool (Stripe, 2026). An outage on your side lasting longer than the retry window loses those events permanently from the push channel. Detecting that gap is its own monitoring problem, and the recovery has to come from somewhere else.

There is a caution in the other direction as well. Stripe advises processing events asynchronously and returning a 2xx quickly, because a spike in deliveries can overwhelm an endpoint that does its work inline (Stripe, 2026). Show week is exactly the spike, so a handler that writes straight to the warehouse will fall over on the one day it was built for.

The limits that arrive sooner than you expect

Subscription caps are the practical constraint nobody plans for. Swapcard enforces "a maximum of 20 webhook subscriptions per event" (Swapcard, 2026). Stripe allows 16 registered endpoints per account (Stripe, 2026). Those sound generous until three teams each want their own feed across a portfolio of eight shows.

The design that survives is to subscribe once, into a queue you own, and fan out from there. Your queue can have as many consumers as you like, it retains messages on your terms rather than the vendor's, and replaying a week is something you can do without asking anybody. It also gives you one place to verify the signature, which is a check with its own failure modes and which you do not want implemented four times slightly differently.

Working the reconciliation on one show week

Illustrative numbers for one show week, Monday to Friday, with doors opening on the Wednesday. Registrations created during the week, according to the platform's own total on Friday at 02:00: 4,318. Webhook messages received across the week: 5,902, which is creates, updates and redeliveries mixed together. Deduplicating on event identifier removes 61 repeats. Filtering to creation events leaves 4,290 distinct registrations seen through the push channel.

The gap is 28 registrations, or 0.65 per cent, that never arrived by webhook. In aggregate that is nothing. As a list of 28 named people who were absent from the 16:00 dashboard, from the badge pre-print file and from the exhibitor matchmaking pool, it is not nothing at all, and one of them will be a buyer somebody was chasing.

Latency in the other direction: median time from registration to webhook receipt of 1.8 seconds, against a worst case of 24 hours on the nightly poll. That is what you are buying, and it is worth a great deal during show week and almost nothing in February.

So the honest summary of this week is that the push channel gave you a 24 hour improvement in freshness and a 0.65 per cent shortfall in completeness, and the poll gave you the reverse. Reporting both, every morning, is the whole discipline. When the gap moves from 0.65 per cent to 4 per cent on a Thursday, you have found a problem on the day rather than in the post-show reconciliation.

When is polling the better answer?

More often than the current fashion suggests, and the cases are easy to name. Poll when the feed is small and the freshness requirement is loose, which describes most integrations for eleven months of the year. Poll when you need a full historical backfill, since a webhook only tells you about things that happen after you subscribe. Poll when the vendor's webhook payload is thin and you would have to call the API for the full record anyway, which turns every push into two round trips. Poll when your endpoint cannot be made publicly reachable, which is a real constraint in some organisations and not worth fighting over a fifteen minute latency improvement.

Push when the reaction has to be immediate: badge printing, access control, a matchmaking pool that should include somebody who registered ten minutes ago, an alert when a named account registers.

The poll's design has its own hazard on a feed that is growing while you read it, and choosing the right paging scheme matters more than the interval does. Getting that wrong produces a poll that is neither complete nor fresh.

Which one is the source of record

Pick the poll, write it down somewhere colleagues will find it, and hold to it when somebody builds a dashboard off the faster feed. The poll is repeatable, it is auditable, and it can be re-run against a past date to reproduce a number somebody queried in November. The webhook stream is a stream: replayable only within the vendor's window, dependent on your uptime at a moment that has passed, and impossible to reconstruct from scratch. Counts, reports and anything that reaches a board pack should come from the poll.

The webhook feed then has a clear job: drive the things that need to happen now, and act as an early warning that the poll will find something different tomorrow. Two roles, one definition each, and no argument about which dashboard is right.

Set the poll's look-back window deliberately. If the vendor retries for three days, a poll that only asks for records changed in the last 24 hours cannot recover a three day outage. Ask for a window comfortably wider than the retry period, accept the extra rows, and deduplicate on your side.

The extra rows are cheaper than they look. A seven day look-back on a feed taking 600 registrations a day pulls 4,200 rows instead of 600, which is seven times the transfer and still a small request by any modern standard. Weigh that against the alternative, which is discovering in the post-show reconciliation that a Thursday outage cost you 340 records with no way to identify which ones. The asymmetry is the argument: over-fetching wastes a few seconds a night, and under-fetching produces a gap you cannot close after the retry window shuts.

Where this stops

Running both costs more than running one. Two code paths, two sets of credentials, two monitoring surfaces, and a reconciliation job that somebody has to look at. On a single annual show with 3,000 registrations and no live requirement, that is over-engineering, and a nightly poll with a morning eyeball is the correct answer.

The deeper limit is that reconciliation tells you the two channels disagree without telling you which is right. Both can be wrong at once. A vendor bug that fails to fire a webhook and a filter in your poll that excludes the same records will agree perfectly and both miss the same 200 people. The only defence is a third reference point, usually the platform's own headline total, which is why the reconciliation should compare three numbers rather than two, in the same way the rest of the integration layer should never trust a single source for a figure it publishes.

Start this week by counting. Take last show week, count distinct registrations seen through your push channel, count the platform's own total for the same period, and write down the difference as a percentage. If you have no push channel yet, that number is 100 per cent and you now know what latency is costing you.

Questions people ask about webhooks versus polling

Do webhooks arrive in the order events happened?
Not necessarily. Stripe states plainly that it does not guarantee delivery of events in the order they were generated, and advises building consumers that do not depend on order. A registration update can therefore reach you before the create it belongs to, so a loader has to either upsert blindly or park the orphan and retry it.
How far back should a reconciliation poll look?
At least as far as the vendor's retry window, and preferably further. Stripe retries for up to three days in live mode, so a delivery that fails for longer is gone for good and a poll with a 24 hour look-back cannot recover it. Match the look-back to the retry window and add a margin.
Is one webhook subscription enough for several consumers?
Rarely, and the caps arrive sooner than teams expect. Swapcard allows a maximum of 20 webhook subscriptions per event and Stripe allows 16 endpoints per account. Subscribe once into your own queue and fan out internally from there, rather than giving every downstream consumer its own subscription against the vendor.