Skip to main content
meridian-pg is a Postgres extension that exposes Meridian CRDT types directly in SQL. A trigger fires pg_notify on every write, and the Meridian server broadcasts the delta to all connected clients in real time.

Install the extension

Requires Postgres 14–17. Built with pgrx 0.13.

Add CRDT columns to a table

CRDT state is stored as BYTEA (msgpack-encoded). Add columns with standard ALTER TABLE:

Attach the sync trigger

The trigger accepts any number of CRDT columns as variadic arguments:
One pg_notify is emitted per changed column per row, on channel meridian_ops:

Write from SQL

Read from SQL

Merge two states

Useful for manual conflict resolution or backfills:

Connect from the SDK

The crdt_id sent over pg_notify is "<prefix>:<pk>:<col>". Use it directly with the SDK:

Server setup

Start the server with DATABASE_URL pointing to the same Postgres instance:
The server LISTENs on meridian_ops and feeds incoming pg_notify payloads into the same apply + WebSocket broadcast pipeline as any other op.

WAL consumer (large documents)

pg_notify has an 8 KB payload limit — large RGA documents or deep Tree edits will be silently dropped by the trigger. For those, enable the WAL consumer in the Meridian server, which tails the logical replication stream instead. The WAL consumer lives server-side (not in the extension). It opens a replication connection to Postgres, parses the pgoutput stream, and feeds BYTEA column changes through the same merge + broadcast path as pg_notify. Both paths coexist and are idempotent — for small documents you get both, for large ones you only get the WAL path.

1. Enable logical replication

2. Start the server with WAL replication enabled

Set MERIDIAN_WAL_CONNSTR to a connection string pointing at the same Postgres instance. The server creates the replication slot and publication automatically on first boot.
If MERIDIAN_WAL_CONNSTR is not set, the server falls back to pg_notify only (no change in behaviour for documents under 8 KB).

Function reference

Building from source

Caveats

  • pg_notify limit — 8 KB. Large RGA / Tree documents should use the WAL consumer instead (see above).
  • RGA / Tree writes — require HLC timestamps; write exclusively via WebSocket clients or the HTTP API. SQL functions are read-only for these types.
  • Clock drift — always pass EXTRACT(EPOCH FROM now())::bigint * 1000 as wall_ms to lww_set. The server validates HLC drift within ±30 s.
  • Trusted ops — ops from pg_notify bypass token auth. Treat DB write access as equivalent to Meridian admin access.