Real-Time Pub/Sub (LISTEN/NOTIFY)

HeliosDB Lite delivers application events with PostgreSQL LISTEN, UNLISTEN and NOTIFY over the wire protocol for updates such as order or inventory changes: one session subscribes to a channel with LISTEN, another announces a change with NOTIFY, and the listening session receives the notification through its standard PostgreSQL driver, so services coordinate without running a separate message broker.

Executive Summary

With thread-safe in-memory channel management, automatic subscription cleanup, and 8KB payload support, HeliosDB Lite enables event-driven applications to implement real-time dashboards, cache invalidation, activity feeds, workflow automation, and microservices coordination entirely within embedded, edge, and microservice deployments without Redis, Kafka, or message queue infrastructure.


Problem Being Solved

Core Problem Statement

Teams deploying to edge devices, embedded systems, or resource-constrained environments cannot afford external message queue dependencies, yet lack a lightweight pub/sub mechanism for event-driven patterns.

Who Suffers Most

  • IoT/Edge Application Developers: Building collaborative tools or real-time monitoring on edge devices where external message brokers are unavailable, forcing them to implement inefficient polling or abandon real-time features entirely, degrading user experience significantly.

Concrete Examples with Code, Config & Architecture

Example 1: Real-Time Dashboard Updates - Embedded Configuration

Architecture:

Web Browser (WebSocket)
    ↓
Web Server (Axum/Actix)
    ↓
HeliosDB-Lite (LISTEN 'sales_updates')
    ↓
In-Process Notification Queue
    ↓
Database Trigger on INSERT → NOTIFY 'sales_updates'

Configuration (heliosdb.toml):

# HeliosDB-Lite configuration for real-time dashboard
[database]
path = "/var/lib/heliosdb/sales.db"
memory_limit_mb = 512
enable_wal = true

[pubsub]
# Enable pub/sub with optimized settings
enabled = true
max_channels = 1000
max_payload_bytes = 8000
notification_queue_size = 100

[monitoring]
metrics_enabled = true
verbose_logging = false

Example 2: Cache Invalidation - Python Integration

Scenario: Multi-instance web application with in-memory caches that must invalidate when source data changes, without polling or manual TTL management.

Architecture Pattern:

┌─────────────────────────────────────────┐
│  Application Instance 1                  │
│  ┌────────────────┐  ┌────────────────┐ │
│  │ In-Memory Cache│  │ LISTEN Thread  │ │
│  └────────────────┘  └────────────────┘ │
├─────────────────────────────────────────┤
│  Application Instance 2                  │
│  ┌────────────────┐  ┌────────────────┐ │
│  │ In-Memory Cache│  │ LISTEN Thread  │ │
│  └────────────────┘  └────────────────┘ │
├─────────────────────────────────────────┤
│         HeliosDB-Lite (Shared)           │
│  Database Trigger → NOTIFY all listeners │
└─────────────────────────────────────────┘

Flow:
1. Instance 1: UPDATE products SET price = 19.99 WHERE id = 1
2. Database Trigger: NOTIFY 'cache_invalidate', 'product:1'
3. All Instances: Receive notification, invalidate local cache
4. Next read: Cache miss, fetch fresh data

Example 3: Activity Feed - Microservices Integration (Go/Rust)

Scenario: Social platform with 10,000 users, displaying real-time activity feed updates (likes, comments, follows) without polling every user's feed.

Service Architecture:

┌─────────────────────────────────────────┐
│     Client (Browser / Mobile App)       │
│     Server-Sent Events (SSE) Stream     │
├─────────────────────────────────────────┤
│     Activity Microservice (Rust)        │
│  ┌────────────────────────────────────┐ │
│  │  POST /activities                  │ │
│  │    ↓                               │ │
│  │  INSERT INTO activities            │ │
│  │    ↓                               │ │
│  │  Trigger fires NOTIFY              │ │
│  └────────────────────────────────────┘ │
│  ┌────────────────────────────────────┐ │
│  │  GET /activities/stream/:user_id   │ │
│  │    ↓                               │ │
│  │  LISTEN 'activity_feed_123'        │ │
│  │    ↓                               │ │
│  │  Poll subscription → SSE stream    │ │
│  └────────────────────────────────────┘ │
├─────────────────────────────────────────┤
│         HeliosDB-Lite (In-Process)      │
│  PubSubManager → Notification Delivery  │
└─────────────────────────────────────────┘

Example 4: Workflow Automation - Docker/Container Deployment

Scenario: Order processing workflow where each step triggers the next automatically via database events, eliminating manual coordination.

Docker Deployment (Dockerfile):

FROM rust:latest as builder

WORKDIR /app
COPY . .
RUN cargo build --release

FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*

COPY --from=builder /app/target/release/workflow-engine /usr/local/bin/

RUN mkdir -p /data

EXPOSE 8080

VOLUME ["/data"]

ENTRYPOINT ["workflow-engine"]
CMD ["--config", "/etc/workflow/config.toml"]

Docker Compose (docker-compose.yml):

version: '3.8'

services:
  workflow-engine:
    build:
      context: .
      dockerfile: Dockerfile
    image: workflow-engine:latest

    ports:
      - "8080:8080"

    volumes:
      - ./data:/data
      - ./config/workflow.toml:/etc/workflow/config.toml:ro

    environment:
      RUST_LOG: "workflow_engine=info"
      HELIOSDB_DATA_DIR: "/data"

    restart: unless-stopped

    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 3s
      retries: 3

networks:
  default:
    driver: bridge

Workflow Configuration (config/workflow.toml):

[database]
path = "/data/workflow.db"
memory_limit_mb = 256
enable_wal = true

[pubsub]
enabled = true
max_channels = 100

[workflow]
# Workflow step definitions
[workflow.steps.payment_processing]
trigger_channel = "order_created"
action = "process_payment"
next_channel = "payment_completed"

[workflow.steps.inventory_allocation]
trigger_channel = "payment_completed"
action = "allocate_inventory"
next_channel = "inventory_allocated"

[workflow.steps.shipping]
trigger_channel = "inventory_allocated"
action = "create_shipment"
next_channel = "shipment_created"

Workflow Architecture:

Order Created (INSERT)
    ↓
Trigger fires NOTIFY 'order_created'
    ↓
Payment Processor (LISTEN 'order_created')
    ↓ (process payment)
    ↓ NOTIFY 'payment_completed'
    ↓
Inventory Allocator (LISTEN 'payment_completed')
    ↓ (allocate inventory)
    ↓ NOTIFY 'inventory_allocated'
    ↓
Shipment Creator (LISTEN 'inventory_allocated')
    ↓ (create shipment)
    ↓ Order Complete

Example 5: Microservices Event Bus - Edge/IoT Deployment

Scenario: IoT sensor network with 100 edge devices coordinating via lightweight event bus for distributed alerting without cloud connectivity.

Edge Device Configuration (edge-config.toml):

[database]
path = "/var/lib/iot/sensors.db"
memory_limit_mb = 64        # Low memory for edge devices
page_size = 512
enable_wal = true

[pubsub]
enabled = true
max_channels = 50
max_payload_bytes = 1024    # Smaller payloads for IoT

[edge]
device_id = "sensor_001"
location = "warehouse_a"

Adoption Strategy

Phase 1: Proof of Concept (Weeks 1-4)

Target: Validate LISTEN/NOTIFY for one real-time feature

Tactics:

  • Replace polling-based cache invalidation with LISTEN/NOTIFY in development environment
  • Measure CPU reduction and latency improvement
  • Test with 100-1000 notifications per second
  • Validate PostgreSQL client compatibility (psycopg2, node-postgres)

Phase 2: Pilot Deployment (Weeks 5-12)

Target: Deploy to production for one critical use case

Tactics:

  • Deploy real-time dashboard or cache invalidation to production
  • Monitor notification latency and throughput with metrics
  • Gather user feedback on real-time update responsiveness
  • Measure infrastructure cost savings (Redis elimination)

Phase 3: Full Rollout

Target: Organization-wide adoption for all event-driven features

Tactics:

  • Expand to all polling-based features (activity feeds, workflow automation, etc.)
  • Implement database triggers for automatic event generation
  • Migrate from Redis Pub/Sub to HeliosDB Lite LISTEN/NOTIFY
  • Document best practices and architectural patterns for team

Conclusion

With transaction-integrated NOTIFY delivery, automatic trigger-based events, and native database integration, HeliosDB Lite transforms event-driven architecture from a complex distributed systems problem into a simple database feature.

Start your proof of concept today: replace one polling-based cache invalidation or real-time dashboard feature with LISTEN/NOTIFY, measure the CPU and latency improvements, and experience the simplicity of event-driven architecture without external dependencies.

Performance depends on workload and hardware. Published figures are measured on representative fixtures; see the benchmarks page and reproduce them on your own workload.