At 50 agents polling every 500ms, your system generates 6,000 reads per minute, most with no new data. Polling is like manually refreshing email every five seconds: functional, but each agent adds infrastructure cost. The latency and load are real, while the information returned is often zero.
Push delivery removes that recurring cost. Rather than asking "has anything changed?" on a schedule, each agent subscribes to relevant state and receives a notification when that state changes. The update arrives when the write commits, not at the next interval. Median notification latency depends on the streaming implementation, not subscriber count, provided the infrastructure scales correctly.
Why teams still choose polling
Polling survives because every database can support it. Put a timestamp filter on a SELECT query, run it in a loop, and the pattern works with Postgres, MySQL, MongoDB, or any system offering basic reads. The agent developer does not need to learn a change notification mechanism because polling has none.
Push delivery needs supporting infrastructure: a database or broker that emits change events, a low-latency protocol for subscribers, and a client SDK with a clear subscription API. When a team needs working code quickly, polling wins on simplicity, even when it loses on resource efficiency.
The turning point usually arrives when polling frequency and agent count make polling reads a meaningful share of database load. We have seen teams where empty polling results represented 40 to 60 percent of all queries. At that level, the operational cost is high enough to justify engineering a push path.
Delivery options
Push-based state delivery can be implemented several ways, with different latency and reliability tradeoffs.
Database change data capture (CDC). Postgres logical replication, MySQL binlog, and similar systems expose write-ahead log events. A consumer reads that stream and forwards relevant changes to agent subscribers. The model is reliable and ordered: an event in the WAL is delivered, and delivery follows write order. The cost is operational overhead. CDC requires a separate consumer process, and the path from WAL write to consumer processing to subscriber forwarding adds practical latency.
Message broker (Kafka, Redis Streams, Pulsar). The application writes to the database and broker at commit, while subscribers consume the broker topic. Teams often choose this after investing in Kafka or Redis. The issue is atomicity: the database write can succeed while the broker write fails, or the reverse, leaving inconsistent systems. Reconciliation logic is then required, reducing the simplicity advantage.
WebSocket or SSE subscriptions backed by the database. The data layer owns subscriptions and sends deltas over persistent connections when relevant documents change. This is the model LaserData implements. Because writes and subscriptions live in one system, there is no dual-write consistency issue. From the application's perspective, committing the state change and notifying subscribers occur in one operation.
Long-polling. The client sends a read request and the server holds it until data is available or the timeout expires. This improves on fixed-interval polling because latency follows change frequency rather than poll interval. It still uses one connection per waiting client and requires server-side management of held connections at scale.
Building LaserData's streaming layer
LaserData's streaming layer uses session-scoped subscriptions. An agent subscribes to changes in one session's state documents. When a write to those documents commits, LaserData sends the delta to every active subscriber for that session before acknowledging the write.
The sequence is direct: the write commits, subscribers receive synchronous notifications on the write path, and the caller then gets the acknowledgment. From the writer's perspective, the update and acknowledgment share one round trip. A waiting subscriber receives the delta with the commit round trip, rather than at a later polling interval.
Subscriptions target document paths or session-scope queries. An agent can request notifications for any document change in session X or for modifications to path Y. Each event contains a delta, meaning changed fields and their new values, rather than a full document. For large documents, that reduces message size when only a few fields change.
The fan-out problem
Many subscribers create fan-out pressure: one write may notify hundreds or thousands of clients. Synchronous fan-out increases write latency as subscriber count rises. Asynchronous fan-out avoids that cost but allows some subscribers to receive the event before others, weakening delivery-order guarantees.
We chose a deliberate split. LaserData's synchronous path covers subscribers sharing a session or document scope, typically the agents most likely to act on the change. Cross-session watchers, such as a coordinator tracking a sub-agent, use asynchronous delivery with a latency target rather than a synchronous guarantee. A subscribe-call parameter lets the application select its required consistency guarantee.
We are not saying synchronous fan-out solves every topology. If thousands of sessions subscribe to one state document, any synchronous implementation will raise write latency. In that case, partition the hot document or filter subscriptions so every agent does not receive every change.
Backpressure and slow subscribers
Without backpressure, push delivery fails differently from polling. A slow polling agent simply waits for its next read. A slow subscriber instead builds a notification queue. If that queue has no bound, it can exhaust server memory or increase delivery latency for other subscribers on the channel.
LaserData gives each subscriber a delivery queue with a configurable depth limit. Once the limit is reached, later notifications are dropped and an event ID gap is recorded in the stream. On reconnect, the SDK detects the gap and performs a reconciliation read for missed state. Slow subscribers therefore receive eventual delivery without blocking faster subscribers on the channel.
Agent code must account for reconciliation. A handler that applies deltas incrementally also needs to recover when a gap requires a full-state refresh. LaserData exposes this condition in the SDK: the subscriber receives either a delta event or a full-state reconcile event. The agent handler must process both.
Comparing polling in practice
We are not saying polling is always wrong. We are saying it is appropriate when state changes rarely and update urgency is low. A billing reconciliation agent running once per hour does not need sub-second delivery, so a reasonable polling interval may be simpler and sufficient.
Push delivery is the clearer fit for tight decision loops, such as waiting for a sub-agent before selecting the next action. It also suits coordinators reacting to progress events and architectures where shared-state polling has become a measurable share of database load.
On LaserData, moving from polling to streaming is a small SDK refactor. Replace the query inside the loop with a subscribe call that opens a persistent connection and invokes a callback for each delta. The rest of the application can remain unchanged. The migration is a refactor, not a rewrite.
Production considerations
These operational patterns matter when adopting push delivery:
Connection management changes with streaming. Persistent connections need a lifecycle distinct from request-response queries, and agents must handle drops and reconnect with session continuity. The LaserData SDK performs reconnect and gap detection automatically, but the agent state machine must process the reconnect event. Do not assume in-memory state still matches the database until the reconcile event is handled.
Track subscriber queue depth as well as delivery latency. A growing queue shows that update processing is falling behind. Once latency visibly degrades, the queue may already be significantly backed up.
Test gap handling directly. Because development networks are stable, the gap and reconcile path is often untested even though it is the recovery path. Add an integration test that pauses a subscriber, lets several writes accumulate, reconnects, and verifies correct handling of the full-state reconcile event.