Skip to main content

Overview

This guide will help you set up PostgreSQL Realtime Monitor from scratch. You’ll have a working real-time database monitor with a React frontend in just a few steps.
Make sure you have Bun and Docker installed before starting.

Installation

1

Install Dependencies

Install all required packages using Bun:
bun install
This installs:
  • postgres - PostgreSQL client with logical replication support
  • react & react-dom - UI framework (v19.2.0)
  • typescript - Type safety and developer experience
2

Start PostgreSQL

Launch PostgreSQL with Docker Compose. This starts a PostgreSQL 16 instance with logical replication enabled:
docker-compose up -d
The database starts with:
  • Host: localhost:5432
  • Database: appdb
  • User: appuser
  • Password: secret
  • Logical Replication: Enabled (wal_level=logical)
  • Publication: alltables (created automatically via init.sql)
docker-compose.yml
version: "3.9"

services:
  db:
    image: postgres:16-alpine
    container_name: postgres-realtime
    restart: unless-stopped
    environment:
      POSTGRES_DB: appdb
      POSTGRES_USER: appuser
      POSTGRES_PASSWORD: secret
    ports:
      - "5432:5432"
    command: >
      postgres
        -c wal_level=logical
        -c max_wal_senders=10
        -c max_replication_slots=10
        -c max_connections=100
    volumes:
      - db-data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
3

Start the Application

Run the Bun development server:
bun run dev
This starts:
  • HTTP Server on http://localhost:3000
  • WebSocket Server on ws://localhost:3000/ws
  • Hot Module Reloading for React components
You should see output like:
🚀 Server running at http://localhost:3000
📡 WebSocket available at ws://localhost:3000/ws
✅ Realtime subscription ready (connected or reconnected)
4

Open in Browser

Navigate to http://localhost:3000You’ll see:
  • A connection status indicator (should show “Connected”)
  • An empty table waiting for database changes
  • Total changes counter at 0

Testing Real-time Updates

Now let’s see the real-time monitoring in action by making database changes.
1

Connect to PostgreSQL

Open a new terminal and connect to the running PostgreSQL container:
docker exec -it postgres-realtime psql -U appuser -d appdb
You should see the PostgreSQL prompt:
psql (16.x)
Type "help" for help.

appdb=#
2

Create a Test Table

Create a simple todos table:
CREATE TABLE todos (
  id SERIAL PRIMARY KEY,
  title TEXT NOT NULL,
  done BOOLEAN NOT NULL DEFAULT false,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
Watch your browser - the table columns will automatically appear once you insert data!
3

Insert Data

Add some todo items and watch them appear instantly in the browser:
INSERT INTO todos (title) VALUES ('Build real-time monitor');
INSERT INTO todos (title) VALUES ('Write documentation');
INSERT INTO todos (title) VALUES ('Deploy to production');
Each INSERT operation will:
  • Appear in the browser immediately
  • Show operation type as INSERT (green badge)
  • Display all column values including auto-generated id and created_at
  • Increment the total changes counter
4

Update and Delete

Try UPDATE and DELETE operations:
-- Mark a todo as done (UPDATE shows in blue)
UPDATE todos SET done = true WHERE id = 1;

-- Delete a todo (DELETE shows in red)
DELETE FROM todos WHERE id = 3;
Watch how:
  • UPDATE operations show in blue badges
  • DELETE operations show in red badges
  • All changes appear instantly without page refresh

Understanding the Architecture

Here’s how the system captures and streams changes:
import postgres from "postgres"

const sql = postgres({
    host: 'localhost',
    port: 5432,
    database: 'appdb',
    username: 'appuser',
    password: 'secret',
    publications: 'alltables', // Subscribe to all tables
})

Interactive Features

The React frontend includes powerful table features:
Click any column header to sort:
  • First click: Sort ascending ↑
  • Second click: Sort descending ↓
  • Third click: Remove sorting
Supports intelligent sorting for:
  • Numbers (numeric comparison)
  • Dates (timestamp comparison)
  • Strings (alphabetical)
Each column has a filter input below the header:
  • Type to filter rows matching that column
  • Multiple filters work together (AND logic)
  • Case-insensitive matching
  • Active filters show count and clear button
The table automatically detects columns from your data:
  • No configuration needed
  • Works with any table structure
  • Columns appear as data arrives
Operations are color-coded for quick identification:
  • INSERT: Green (#10b981)
  • UPDATE: Blue (#3b82f6)
  • DELETE: Red (#ef4444)

API Endpoints

The server exposes two endpoints:
# Get all accumulated changes
curl http://localhost:3000/api/changes

Configuration

To connect to a different PostgreSQL instance, edit db.ts:
db.ts
export const sql = postgres({
    host: 'your-host',
    port: 5432,
    database: 'your-database',
    username: 'your-user',
    password: 'your-password',
    publications: 'alltables',
})
Your PostgreSQL instance must have:
  • wal_level=logical in postgresql.conf
  • A publication created: CREATE PUBLICATION alltables FOR ALL TABLES;

Troubleshooting

Check that the Bun server is running:
bun run dev
Verify the server started successfully and shows:
✅ Realtime subscription ready (connected or reconnected)
Ensure PostgreSQL is configured correctly:
-- Check wal_level
SHOW wal_level; -- Should be 'logical'

-- Check publication exists
SELECT * FROM pg_publication;
If the publication is missing:
CREATE PUBLICATION alltables FOR ALL TABLES;
Change the port in src/index.ts:
const server = serve({
  port: 3001, // Change to any available port
  // ...
});
Update the WebSocket URL in src/App.tsx to match:
const ws = new WebSocket("ws://localhost:3001/ws");
Check if port 5432 is already in use:
lsof -i :5432
To use a different port, edit docker-compose.yml:
ports:
  - "5433:5432"  # Host:Container
Then update db.ts accordingly:
port: 5433,

Next Steps

Architecture Deep Dive

Learn how the real-time system works under the hood

API Reference

Explore WebSocket messages and REST endpoints

Configuration Guide

Customize database connections and server settings

Usage Examples

Learn common workflows and usage patterns

Build docs developers (and LLMs) love