Skip to content

impulse-studio/pglite-electric-poc

Repository files navigation

PGLite + ElectricSQL POC

A local-first todo app that demonstrates real-time sync between browser tabs using PGLite (Postgres in the browser via WASM) and ElectricSQL (real-time sync engine).

Architecture

[Browser Tab 1]          [Browser Tab 2]
  PGLite (WASM)            PGLite (WASM)
      |                        |
      v                        v
  Electric Client          Electric Client
      |                        |
      +---- HTTP SSE ----------+
                |
       Electric Sync Service
                |
          Server Postgres
                ^
                |
         Express API (writes)
  • Reads: come from local PGLite (instant, no network roundtrip)
  • Writes: go through the Express API → Postgres
  • Sync: Electric streams Postgres changes to all browser tabs via HTTP SSE

Stack

Layer Tech
Frontend Vite + React + TypeScript
Local DB PGLite (@electric-sql/pglite)
Sync ElectricSQL (@electric-sql/pglite-sync)
Styling Tailwind CSS
API server Express + node-postgres
DB Postgres 16
Infrastructure Docker Compose

Prerequisites

Setup

1. Start Postgres + Electric

docker compose up -d

This starts:

  • Postgres 16 on port 5432 (with wal_level=logical for CDC)
  • Electric sync service on port 3000

Wait a few seconds for both services to be healthy.

2. Install dependencies

Frontend:

npm install

API server:

cd server && npm install && cd ..

3. Configure environment (optional)

Copy .env.example to .env.local in the root if you need to change defaults:

cp .env.example .env.local

Default values:

  • VITE_ELECTRIC_URL=http://localhost:3000 — Electric sync service
  • VITE_API_URL=http://localhost:3001 — Express API server

4. Start the API server

cd server && npm run dev

5. Start the Vite frontend

In a new terminal:

npm run dev

The app runs at http://localhost:5173

Demo: Real-time sync

  1. Open http://localhost:5173 in two browser tabs
  2. Add a todo in Tab 1 → it appears in Tab 2 within ~1 second
  3. Toggle or delete in either tab → syncs to the other

Changes are also persisted in PGLite (IndexedDB) — reload the page and todos are still there without a network request.

Project Structure

pglite-electric-poc/
├── src/
│   ├── components/
│   │   ├── AddTodo.tsx      # Form to create todos (calls API)
│   │   ├── TodoItem.tsx     # Single todo row (toggle/delete via API)
│   │   └── TodoList.tsx     # Live-queried list from PGLite
│   ├── db.ts                # PGLite setup + Electric sync init
│   ├── App.tsx
│   ├── main.tsx
│   └── index.css
├── server/
│   ├── index.ts             # Express API (CRUD → Postgres)
│   ├── migrations/
│   │   └── init.sql         # Schema (run on first Postgres start)
│   └── package.json
├── docker-compose.yml
├── vite.config.ts
└── package.json

How it works

  1. PGLite creates a full Postgres instance in the browser (via WASM), persisted in IndexedDB
  2. electricSync extension connects to the Electric service and syncs the todos shape into the local PGLite table
  3. useLiveQuery hook re-renders the UI whenever PGLite data changes
  4. Writes hit the Express API → Postgres → Electric detects the WAL changes → pushes to all connected clients → PGLite updates → React re-renders

About

POC: PGLite + ElectricSQL — Real-time sync with local Postgres in the browser

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors