The reputation, and what it costs
Polling has a bad reputation, and naive polling has earned it. Thousands of clients asking every five seconds, 99 percent of the answers empty, and the load scaling with how many clients you have rather than how much is happening.
Weigh that against what a reliable webhook consumer actually costs you: signature checking, async processing, deduplication, a dead letter queue, reconciliation. There are plenty of situations where a polling loop gets the same outcome for a tenth of the work.
Poll when you cannot receive calls at all. A service behind a corporate firewall, a script on a laptop, a mobile app, a batch job with no stable public address.
Poll when the provider has no webhooks, or offers them with no signatures and no retries, in which case their list endpoint is the only interface you can trust.
Poll when freshness barely matters. If a dashboard syncing every 15 minutes is fine, a scheduled job hitting a list-changes endpoint is your entire architecture. No public endpoint to secure and no failed deliveries to chase, because each poll is its own retry.
Polling is more correct for state
Prefer it for keeping state in sync, where it is simply more correct. Webhooks tell you what happened; polling tells you what is.
Notice the asymmetry there. A missed webhook is a permanent gap unless you reconcile it, while a missed poll is corrected by the next poll, because every poll fetches the current state.
That self-healing property is why even heavy webhook users poll underneath, and why the mature answer is both. Webhooks for latency, polling for truth.
Refine it two ways and polling becomes respectable at scale. Ask only for what changed since your last position, which keeps every response small and cheap. And when you need low latency without webhook machinery, hold the request open until data arrives or a timeout passes. That gets you close to push while staying an ordinary HTTP client.
Worked example
Diego's team syncs inventory from a warehouse management system into their storefront. The WMS offers webhooks, but they are unsigned, retry only once, and the WMS vendor's status page shows webhook incidents monthly. Rather than build trust infrastructure on an untrustworthy sender, Diego writes a poller: every 60 seconds it calls the WMS list endpoint with updated_since set to the last watermark, fetching around 200 changed SKUs per cycle out of a 40,000-SKU catalog. The whole integration is 150 lines plus a cron entry, and there is no public endpoint to secure or monitor. When the WMS has a four-hour outage in May, the poller just finds four hours of changes in its next successful cycle and catches up in two polls. Stock levels lag by at most a minute, which merchandising confirmed nobody can perceive. The webhook integration remains unbuilt, deliberately.