Real-time notifications in Drupal with WebSockets
Drupal sites often begin with email, polling, or a page refresh to signal that content, comments, orders, or moderation items have changed. Those approaches work, but they can feel delayed during busy editing sessions. A persistent browser connection allows the interface to surface changes as they happen, giving administrators and authenticated visitors a more responsive experience.
Drupal normally operates as a request-and-response application: PHP builds a page, the browser receives it, and server activity ends. Real-time notifications in Drupal with WebSockets require an additional gateway that holds a full-duplex connection and distributes events. Drupal remains responsible for data and permissions, while the gateway handles subscriptions and rapid delivery.
The implementation must also survive token expiry, dropped connections, duplicated messages, and horizontal scaling. Teams need clear channel rules, privacy controls, observable delivery, and a notification design that remains useful when live updates are unavailable. The result should enhance core Drupal workflows rather than become a separate messaging product.
Architecture for live Drupal updates
Drupal core does not provide a persistent WebSocket endpoint. A practical design starts with a custom module or contributed integration that detects relevant changes, such as a node being published, a comment awaiting approval, or an order changing status. These hooks create a small event record containing an event ID, type, recipient or channel, timestamp, and minimum payload.
A separate gateway accepts browser connections and publishes those records to channels. Redis often sits between Drupal and multiple gateway instances, allowing one application server to emit an event while every connected gateway can deliver it. The browser subscribes only to authorised channels and renders a toast, unread count, or refreshed panel.
Delivery should be treated as at-least-once rather than exactly once. Sequence numbers, acknowledgements, and client-side de-duplication prevent repeated alerts, while a durable queue or replay store closes the small gap that ordinary pub/sub can leave during a disconnect. Presence indicators and important domain events should be designed separately because a missed presence update is less serious than a missed order update.
Selecting a WebSocket platform
A hosted realtime service can reduce infrastructure work, while a self-hosted Node.js, Go, or Elixir gateway offers greater control over data paths and protocols. Compare connection limits, regional endpoints, authentication features, message retention, observability, and the realistic cost of operating idle capacity. The busiest channel, not the average user, determines capacity requirements.
Australian data-residency requirements often favour a Sydney or Melbourne cloud region when customer information must remain nearby, although the legal assessment depends on the application. Store event timestamps in UTC and render them in the viewer’s locale. Perth runs at UTC+8, while Sydney, Melbourne, and Brisbane move between UTC+10 and UTC+10:30 during daylight-saving periods, so local-time assumptions can produce misleading alerts.
The gateway should normally use TLS on port 443 and support HTTP Upgrade headers through the load balancer. Teams already operating virtualised Drupal infrastructure can use vSphere deployment practices to align host sizing, monitoring, and resilience with the gateway. Confirm connection limits, idle timeouts, proxy buffering, and health checks before committing to a platform.
Securing connections and Drupal permissions
Do not treat a long-lived connection as an invitation to bypass Drupal access checks. A same-origin request can issue a short-lived, signed token after checking the user session and CSRF protection. The gateway validates its signature, expiry, audience, and scopes, then grants subscriptions for that user. Expired tokens trigger a fresh Drupal check instead of extending access indefinitely.
Validate the browser Origin header against an allowlist, use wss://, restrict message sizes, and rate-limit connection and token requests. Keep credentials out of query strings because proxy logs tend to retain them. CSP connect-src rules should name only the trusted gateway, and logout or a permissions change should invalidate active subscriptions where practical.
The Australian Privacy Act 1988 and Australian Privacy Principles still apply to personal data processed for notifications, while commercial email or SMS campaigns may engage the Spam Act 2003. Put marketing consent and channel preferences in Drupal, separate operational alerts from promotional messages, and send only the minimum event data needed for each recipient. A channel name alone must never reveal a private order, draft, or moderation queue.
Building the notification workflow
Start with an explicit event catalogue. Define stable names such as node.published, comment.awaiting_review, and order.status_changed, then document which roles can receive each event. A transactional outbox is useful here: Drupal writes the notification record in the same database transaction as the source change, and a queue worker publishes it to Redis or another broker. This avoids losing an event when a database commit and network request happen at different times.
The Drupal module can expose a controller for token issuance and keep gateway credentials in configuration rather than source code. A queue worker, cron task, or small dispatcher reads outbox rows, publishes them, and marks successful deliveries. The gateway should not query Drupal for every frame; it can consume compact events and let the browser request current data through a protected Drupal route when more detail is required.
On the browser side, a small JavaScript client manages the connection, channel subscriptions, heartbeats, and reconnections. Exponential backoff with jitter prevents a server restart from triggering a connection storm. Event IDs and sequence numbers let the client discard duplicates, while aria-live="polite" announcements make urgent updates accessible without relying on sound. Drupal behaviors or a custom library can attach the client through drupalSettings.
Scaling and operating the service
Separate gateway nodes behind a load balancer and use Redis pub/sub for ordinary fan-out. Pub/sub is fast but transient; use a durable stream when events must survive a subscriber outage. Capacity planning should cover simultaneous sockets, messages per second, payload size, token validation, and the reconnect rate after deployments. Autoscaling helps, but it does not replace queue depth alerts and tested limits.
Monitor connection counts, publish failures, consumer lag, handshake errors, TLS expiry, and browser reconnect frequency. Configure idle timeouts and keepalive behaviour deliberately, because proxies can close quiet connections before the browser notices. During releases, drain gateway nodes, finish active deliveries, and keep a stable version available for clients that reconnect to another instance.
Distance and connection quality matter across Australia. Teams in Sydney, Melbourne, Brisbane, Perth, and Adelaide may connect through different NBN plans, fixed wireless, or mobile broadband, with variable latency and occasional outages. Offline detection, cached unread counts, and jittered reconnection make the service dependable on variable links and useful for distributed teams working outside major metropolitan centres.
Testing delivery and comparing options
Test the complete path from a Drupal change to the browser frame. Browser developer tools show the WebSocket handshake and frames, while gateway and worker logs should share a correlation ID. During development, inspect proxy upgrades, verify the Origin header, and confirm that token expiry produces a controlled re-authentication rather than an endless reconnect loop. Also test anonymous users, role changes, and deleted content.
Send duplicate and out-of-order events deliberately, then kill the gateway during publication. The client should reconnect, recover unread state, and avoid replaying old toasts. Load tests should model short bursts, slow consumers, and the reconnect wave that follows maintenance. Accessibility checks should cover screen-reader announcements, keyboard dismissal, focus, and reduced-motion preferences.
A compact comparison clarifies the operational trade-offs:
| Approach | Advantages | Main trade-offs | Strong fit |
|---|---|---|---|
| Hosted realtime service | Fast setup, managed connections, regional delivery | Recurring fees and provider dependency | Small teams and rapid launches |
| Self-hosted Socket.IO gateway | Full protocol control and flexible integration | Capacity, TLS, monitoring, and upgrades remain internal | Established platform teams |
| Purpose-built WebSocket service | Small runtime and precise control | More custom engineering and testing | Large or highly specialised platforms |
The practical choice depends on staffing and event criticality. Managed services suit straightforward editorial alerts; self-hosting becomes attractive when protocol control, data placement, or high connection counts justify a dedicated operational role.
A practical notification rollout checklist
Release the infrastructure and Drupal module before enabling user-facing alerts, then use a feature flag and a per-channel kill switch. Start with one low-risk event, such as a moderation update, and observe behaviour during Australian business hours. Local market expectations are unforgiving: shoppers accustomed to prompt feedback from Woolworths, Coles, JB Hi-Fi, and digital-first retailers can interpret silence as a failed order or unavailable item.
- Define event names, payloads, recipients, retention, and access rules before creating channels.
- Issue short-lived gateway tokens and re-check Drupal permissions after token renewal.
- Record events through a transactional outbox and publish them through monitored workers.
- Add dashboards for active sockets, delivery failures, queue lag, reconnects, and token errors.
- Test load balancers, proxies, mobile networks, screen readers, and reconnection behaviour.
- Roll out by team, role, or region while retaining a fast switch for noisy event types.
A measured rollout produces a feature that fits Drupal rather than overwhelming editors. Keep the initial event set narrow, document ownership for Drupal, gateway, and queue components, and review adoption during the next rostered shift across each state-based team. Quiet hours, notification fatigue, and declining open rates are operational signals, not just editorial details.