Polling anti-pattern
Understand why polling for state changes wastes resources and adds latency, when to replace it with webhooks, Server-Sent Events, or WebSockets, and how to evaluate the trade-offs.
TL;DR
- Polling asks "did anything change?" on a schedule. At scale, most polls return "no," burning compute, connections, and network bandwidth for nothing.
- 10,000 clients polling every 5 seconds = 2,000 requests per second to your server, 99%+ of which return empty responses.
- Replace polling with webhooks (you call them when something changes), Server-Sent Events (push a stream over HTTP), or WebSockets (full-duplex persistent connection), each suited for different scenarios.
- Polling is acceptable when the update frequency is low and the acceptable latency is high. For anything near real-time, it's the wrong choice.
The Problem
It's Monday morning. Your job processing platform launched last week. Users submit async jobs and want to know when they're done, so your frontend polls GET /jobs/{id}/status every 2 seconds until the job completes.
Jobs typically take 30 to 120 seconds. In that window, here's what happens:
- 10,000 concurrent users = 5,000 status requests per second
- Each request hits your database to read the status field
- 98% of them return "RUNNING" (the same response as the last poll)
- You're load-testing your database with 5,000 reads/second to deliver no new information
Scale this to 100,000 concurrent users and your status endpoint serves 50,000 requests/second, all reading the same "still running" value from the same rows. You've built an in-house DDoS against your own database.
I saw this exact scenario take down a production Postgres instance. The status table had no read replica, no caching layer, and 50,000 identical SELECT queries per second. The database CPU hit 100%, which slowed actual job processing, which made jobs take longer, which meant more polling. A death spiral.
The Wasteful Math
The economics of polling are brutal at scale:
Polling interval: 5 seconds
Active clients: 10,000
Requests per second: 10,000 / 5 = 2,000 req/s
Expected update frequency: 1 update per 60 seconds per client
Useful requests per second: 10,000 / 60 β 167 req/s
Waste ratio: (2,000 - 167) / 2,000 = 91.6% of all requests return no new data
The faster the interval, the higher the waste. The lower the update frequency, the higher the waste.
| Interval | Clients | Requests/sec | Useful/sec | Waste |
|---|---|---|---|---|
| 2s | 10,000 | 5,000 | 167 | 96.7% |
| 5s | 10,000 | 2,000 | 167 | 91.6% |
| 10s | 10,000 | 1,000 | 167 | 83.3% |
| 2s | 100,000 | 50,000 | 1,667 | 96.7% |
At 50,000 requests/second, you're paying for infrastructure to serve responses that nobody needs. Each request consumes a TCP connection, a thread (or event loop tick), a database read, serialization, and network bandwidth. Multiply by 96.7% waste and you understand why polling doesn't scale.
Why It Happens
Polling is the simplest possible notification mechanism, and simplicity is seductive.
"It works in development." With 5 test users, polling every 2 seconds is 2.5 requests/second. Your laptop handles that without blinking. The problem only surfaces at 10,000+ concurrent users, which you never test locally.
"We don't control the client." If you're building a public API, you can't force clients to implement webhooks or SSE. Polling is the lowest-common-denominator approach that works from any HTTP client, even curl in a loop.
"The frontend team wanted something quick." SSE requires server-side connection management. WebSockets need a load balancer that supports sticky sessions or connection-aware routing. Polling is a GET request in a setInterval. It ships in 30 minutes.
"We'll optimize later." Except "later" is always after the next feature. By the time polling becomes a problem, it's baked into the client SDK, documented in the API docs, and used by external integrators. Ripping it out is a breaking change.
"We tried webhooks but firewalls blocked them." Corporate networks often block inbound connections to client machines. This is a real constraint for B2B integrations, and it's why long polling exists as a middle ground.
How to Detect It
Continue Reading with Premium
Unlock this article and every other in-depth system design guide on the platform with NotesFromSDE Premium.