Skip to content

PATTERN Cited by 1 source

LISTEN/NOTIFY push with polling fallback

Problem

An operator dashboard needs real-time visibility into task queue state (e.g., status transitions, progress). Options include: - External pub/sub (Redis, Kafka) — adds infrastructure. - WebSocket server — adds complexity and operational surface. - Polling only — high latency or high load depending on interval.

Solution

Use Postgres-native LISTEN/NOTIFY as the push channel. State changes in the task table fire NOTIFY events. The backend maintains a single LISTEN connection and fans events out over Server-Sent Events (SSE) to connected browser clients. Updates arrive within ~1 second of each state change.

Permanent polling is retained as fallback at a default 10-second interval. Streaming connections through cloud ingress proxies (ALB, Cloudflare, nginx) can silently drop bytes without firing client-side error events. Polling ensures the dashboard remains current even under these conditions.

A UI indicator distinguishes between live (SSE active) and polling (SSE unavailable) channels so operators know the freshness of displayed data.

Key properties

  • No external message bus — LISTEN/NOTIFY is built into Postgres; no Redis, no WebSocket server, no separate infrastructure.
  • Sub-second push latency — events propagate as soon as the triggering transaction commits.
  • Graceful degradation — polling fallback handles proxy-level connection issues that are invisible to the application.
  • Transparency — UI shows which mode is active, preventing stale-data confusion.

Trade-offs

  • LISTEN/NOTIFY has no durability — missed events during reconnection require the polling path to catch up.
  • High-fan-out scenarios (thousands of concurrent dashboard clients) may stress a single LISTEN connection; would need connection pooling or dedicated pub/sub at that scale.
  • Proxy timeout configuration (ALB idle timeout, nginx proxy_read_timeout) must be tuned to keep SSE connections alive.

Seen in

Last updated · 591 distilled / 1,796 read