Most engineers think Push is more advanced than Pull.
It's an easy conclusion to reach.
After all:
Polling feels old.
WebSockets feel modern.
Realtime feels better than waiting.
But some of the largest distributed systems in the world deliberately choose Pull.
Not because Pull is better.
Not because their engineers haven't heard of WebSockets.
Because every distributed system eventually faces a more important question:
Who is responsible for discovering change?
And the answer to that question determines where complexity lives.
At scale, Pull wastes requests.
Push wastes state.
Most architectures are simply deciding which waste is cheaper.
The Real Problem Isn't Communication
Imagine an order is created.
Order Created
Several services care about it:
Inventory Service
Analytics Service
Notification Service
Billing Service
The problem isn't generating information.
The problem is delivering it.
And there are only two fundamental ways to do that.
Pull
Consumers discover changes themselves.
Analytics ----> Order Service
Inventory ----> Order Service
Notification -> Order Service
Each consumer periodically asks:
"Anything new?"
The responsibility belongs to the consumer.
Push
The producer distributes changes.
Order Service
|
+----> Analytics
|
+----> Inventory
|
+----> Notification
The responsibility belongs to the producer.
That's it.
That's the entire Push vs Pull debate.
Polling, Long Polling, SSE, and WebSockets are merely different ways of implementing these two ideas.
Why Pull Refuses to Die
A common misconception among younger engineers is:
Push is the future.
Pull is a legacy workaround.
Reality is less exciting.
Many highly scalable systems intentionally choose Pull.
Kubernetes Is A Great Example
Imagine a Kubernetes cluster containing 10,000 nodes.
Many engineers expect the control plane to constantly push work to nodes.
Instead, nodes continuously ask:
Any new Pods for me?
The nodes pull work.
The control plane doesn't chase them.
Why?
Because Push concentrates responsibility.
Consider the alternative:
Control Plane
|
+--> Node 1
+--> Node 2
+--> Node 3
...
+--> Node 10,000
Now the control plane must know:
Which nodes are alive
Which nodes are reachable
Which nodes need updates
Which connections failed
Complexity accumulates at the center.
With Pull:
Node 1 ---->
Node 2 ---->
Node 3 ---->
Node N ---->
Each node becomes responsible for its own synchronization.
This is a pattern you'll see repeatedly in distributed systems:
When coordination becomes expensive, systems often shift responsibility to the edges.
Pull tends to distribute complexity.
Polling: The Simplest Pull Strategy
Polling is often mocked because it seems inefficient.
A client repeatedly asks:
Anything new?
Every few seconds.
For example:
GET /orders/123/status
Most responses look identical:
{
"status": "COOKING"
}
Again.
{
"status": "COOKING"
}
Again.
{
"status": "COOKING"
}
Eventually:
{
"status": "DELIVERED"
}
This creates obvious waste.
Consider:
100,000 clients
poll every 5 seconds
That's:
20,000 requests/sec
even when nothing changes.
Which leads many engineers to conclude:
Polling doesn't scale.
But that's not entirely true.
Polling scales surprisingly well operationally.
Why?
Because stateless systems are easier to operate.
The server receives a request.
Returns a response.
Forgets everything.
No connection state.
No heartbeats.
No reconnection logic.
No presence tracking.
Sometimes infrastructure simplicity is worth more than network efficiency.
The Moment Systems Start Moving Toward Push
The problem with polling isn't that it doesn't work.
The problem is that most requests are useless.
A system designer eventually notices:
Request
No Change
Request
No Change
Request
No Change
Request
Actual Update
We're spending resources discovering nothing.
This realization leads to Long Polling.
Long Polling: Let Me Know When Something Happens
Instead of asking every few seconds:
Anything new?
The client asks:
Tell me when something changes.
The request remains open.
Client ---------------- Server
waiting...
When an event appears:
New Message
The server responds immediately.
The client opens another request.
This dramatically reduces wasted requests.
The responsibility is still largely Pull-based.
But the behavior begins to resemble Push.
Long Polling became the bridge between traditional request-response systems and modern realtime systems.
SSE: Realtime Without Realtime Infrastructure
Long Polling still has a cost.
After every event:
Connection closes
A new connection must be established.
SSE removes that overhead.
One connection remains open.
Client ------------------------ Server
The server continuously streams updates.
AAPL = 210
AAPL = 211
AAPL = 212
No reconnects.
No repeated requests.
Just a stream.
This is why SSE quietly powers dashboards, monitoring systems, reporting platforms, and internal tooling.
Not because it's flashy.
Because it's operationally boring.
And boring systems are often excellent systems.
Why WebSockets Change Everything
WebSockets introduce a fundamentally different model.
Instead of:
Request
Response
You get:
Client <-----------------> Server
Both sides can communicate whenever they want.
This is essential for:
Chat systems
Multiplayer games
Collaborative editing
Trading platforms
The benefit is obvious:
Event Created
↓
Event Delivered
almost instantly.
Latency becomes tiny.
User experience improves dramatically.
Which is why founders love realtime.
The Cost Nobody Talks About
Most discussions about WebSockets focus on latency.
Experienced architects worry about something else:
State.
Polling wastes requests.
Push systems accumulate state.
A polling server can forget a client immediately after responding.
A WebSocket server cannot.
The server must remember:
User ID
Connection ID
Subscriptions
Heartbeat Status
Presence Information
And it must remember that information continuously.
Now imagine:
10 million connected users
Suddenly you're not managing APIs anymore.
You're managing connections.
And connections become infrastructure.
This is why large realtime companies eventually build:
Connection Gateways
Presence Services
Fanout Systems
Realtime Clusters
Event Brokers
The complexity didn't disappear.
It moved.
The Business Question Behind Push vs Pull
Engineers often evaluate Push and Pull through a technical lens.
Founders and CTOs usually care about a different question:
What will this cost us to operate?
Polling often creates more infrastructure waste.
Push often creates more engineering complexity.
Polling may consume more requests.
Realtime systems may require entire teams dedicated to connection management.
Founders often optimize for user experience.
CTOs often optimize for operational complexity.
Architects spend their careers balancing the two.
How Systems Usually Evolve
Most systems don't start with WebSockets.
They grow into them.
Stage 1
Polling
↓
Stage 2
Long Polling
↓
Stage 3
SSE
↓
Stage 4
WebSockets
↓
Stage 5
WebSockets + Pub/Sub + Fanout Services + Event Infrastructure
This evolution appears repeatedly across the industry.
Not because engineers love complexity.
Because scale eventually demands it.
The Hidden Tradeoff
Most engineers frame the decision like this:
Polling vs WebSockets
System designers frame it differently:
Waste vs State
Polling wastes requests.
Push systems accumulate state.
Pull systems tend to distribute responsibility.
Push systems tend to concentrate responsibility around delivery and state management.
Neither side wins.
Both pay.
The only question is:
Which cost is cheaper for your business?
The Mental Model That Actually Matters
Junior engineers often ask:
Should we use WebSockets?
Senior engineers ask:
Where should complexity live?
Should consumers be responsible for discovering change?
Or should producers be responsible for distributing it?
Because Push vs Pull is not really a networking discussion.
It's a complexity allocation discussion.
And every architecture eventually pays the bill.
The only question is who pays it.
Final Thought
Every Pull system eventually asks:
Why are we wasting so many requests?
Every Push system eventually asks:
Why are we managing so much state?
The goal of architecture is not to eliminate complexity.
The goal is to decide where it lives.
Top comments (0)