> Canonical URL: https://codingcat.dev/course/local-first-web-apps-pglite-electric-sql

# Local-First Web Apps: PGlite (WASM Postgres) & Real-Time Sync | CodingCat.dev Course

🧶 CodingCat.dev Course5 Lessons[![](/logos/tags/sql-symbol-light.svg)![](/logos/tags/sql-symbol-dark.svg)SQL](/topic/sql)[![](/logos/tags/typescript-symbol-light.svg)![](/logos/tags/typescript-symbol-dark.svg)TypeScript](/topic/typescript)[#AI & Agents](/topic/ai)[![](/logos/tags/cloudflare-symbol-light.svg)![](/logos/tags/cloudflare-symbol-dark.svg)Cloudflare](/topic/cloudflare)[▶ Watch Course Playlist on YouTube ↗](https://youtu.be/ZD8j6K3-ArU)[Start Course →](/course/local-first-web-apps-pglite-electric-sql/lesson/running-postgres-in-browser-wasm-pglite-opfs)

# Local-First Web Apps: PGlite (WASM Postgres) & Real-Time Sync

![](https://cdn.sanity.io/images/hfh83o0w/production/c0aaa4007ae983fdc5ee4bcb4b2afadfaf6a44a2-1376x768.png?rect=6,0,1365,768&w=1920&h=1080&q=82&fit=max&auto=format)[@CodingCatDev62.5K / 100K Subscribers Goal](https://www.youtube.com/@codingcatdev?sub_confirmation=1)[Subscribe on YouTube→](https://www.youtube.com/@codingcatdev?sub_confirmation=1)[Watch on YouTube App ↗](https://www.youtube.com/watch?v=ZD8j6K3-ArU&list=UUnKZ8gEb78zXKMi1ns-IQ2g)[![Alex Patterson](https://cdn.sanity.io/media-libraries/mlttp0BZbCpV/images/a606dfaa381aab08ddbe16a33fe1d3e1fb37c927-400x400.jpg?w=96&h=96&q=82&fit=max&auto=format)Alex Patterson](/author/alex-patterson)

## course lessons.

1 Section &middot; 5 Lessons1

### Core Architecture & Production Implementation

- [1.1Running Real Postgres in the Browser with PGlite (WASM) & OPFSWhy wait 150 milliseconds for a cloud API round-trip just to filter a table of 5,000 rows? Let's boot genuine PostgreSQL compiled to WebAssembly right inside the browser with PGlite and OPFS.![](/logos/tags/rust-symbol-light.svg)![](/logos/tags/rust-symbol-dark.svg)Rust![](/logos/tags/postgresql-symbol-light.svg)![](/logos/tags/postgresql-symbol-dark.svg)PostgreSQL![](/logos/tags/pglite-symbol-light.svg)![](/logos/tags/pglite-symbol-dark.svg)PGlite▶ Video + LessonStart Lesson →](/course/local-first-web-apps-pglite-electric-sql/lesson/running-postgres-in-browser-wasm-pglite-opfs)
- [1.2Reactive SQL Subscriptions with PGlite Live Queries & Multi-Tab BroadcastKeeping multiple browser tabs and React components in sync after a local database write usually turns into event-emitter spaghetti. Let's replace manual cache invalidation with PGlite Live Queries and multi-tab worker election.![](/logos/tags/react-symbol-light.svg)![](/logos/tags/react-symbol-dark.svg)React![](/logos/tags/sql-symbol-light.svg)![](/logos/tags/sql-symbol-dark.svg)SQL![](/logos/tags/pglite-symbol-light.svg)![](/logos/tags/pglite-symbol-dark.svg)PGlite+1▶ Video + LessonStart Lesson →](/course/local-first-web-apps-pglite-electric-sql/lesson/reactive-sql-subscriptions-pglite-live-queries-react)
- [1.3Streaming Cloud Postgres to the Browser with ElectricSQL ShapesWriting your own real-time sync engine between cloud Postgres and the browser is a notorious distributed-systems trap. Let's stream filtered subsets of cloud Postgres directly into PGlite using ElectricSQL Shapes.![](/logos/tags/postgresql-symbol-light.svg)![](/logos/tags/postgresql-symbol-dark.svg)PostgreSQL![](/logos/tags/pglite-symbol-light.svg)![](/logos/tags/pglite-symbol-dark.svg)PGlite▶ Video + LessonStart Lesson →](/course/local-first-web-apps-pglite-electric-sql/lesson/real-time-postgres-sync-electricsql-shapes-pglite)
- [1.4The Local-First Write Path: Optimistic Outbox, Rollbacks & Conflict ResolutionRead-path sync is easy, but what happens when a user edits ten records offline, closes their laptop, and reconnects hours later? Let's engineer a rock-solid Local-First write path with a durable OPFS outbox.![](/logos/tags/pglite-symbol-light.svg)![](/logos/tags/pglite-symbol-dark.svg)PGlite▶ Video + LessonStart Lesson →](/course/local-first-web-apps-pglite-electric-sql/lesson/local-first-write-path-optimistic-outbox-conflict-resolution)
- [1.5Zero-Backend Hybrid Search in the Browser with PGlite pgvector & Full-Text RRFYou don't need a two-hundred-dollar-a-month cloud vector database to give users semantic search over their workspace. Let's combine PGlite's built-in pgvector extension with Postgres full-text search using Reciprocal Rank Fusion right inside the browser.![](/logos/tags/supabase-symbol-light.svg)![](/logos/tags/supabase-symbol-dark.svg)Supabase![](/logos/tags/postgresql-symbol-light.svg)![](/logos/tags/postgresql-symbol-dark.svg)PostgreSQL![](/logos/tags/pglite-symbol-light.svg)![](/logos/tags/pglite-symbol-dark.svg)PGlite+2▶ Video + LessonStart Lesson →](/course/local-first-web-apps-pglite-electric-sql/lesson/in-browser-hybrid-search-pglite-pgvector-fts)

## course overview.

## 1. Production Architecture Problem & Why We Built This Course

Run full Postgres inside the browser via WebAssembly with PGlite, persist to OPFS, sync state in real time with ElectricSQL Shapes, and build zero-latency offline-capable web apps. In production engineering teams, the gap between a quick weekend demo and a resilient, multi-tenant system comes down to three architectural boundaries: cold-start latency, compile-time contract validation, and predictable operational cost. Throughout **Local-First Web Apps: PGlite (WASM Postgres) & Real-Time Sync**, we strip away marketing buzzwords and build the exact TypeScript, edge compute, and structured data patterns that power [CodingCat.dev](/courses) in production.

Every lesson in this course pairs a dark-mode **Architecture Diagram**  (contrasting the legacy anti-pattern on the left against the recommended 2026 production pattern on the right) with copy-pasteable TypeScript modules, automated verification checks, and an explicit **Trade-Off Matrix**. Whether you are reading the official [PGlite by ElectricSQL: Official WebAssembly Postgres Documentation](https://pglite.dev/docs/) or pairing this course with our deep dive on [Course: The Odin Project 7: Relational Databases, SQL Indexing & Drizzle ORM](/course/odin-databases-and-sql), you can apply every pattern directly to your own repository today.

> 🐾 AJ's Course Architecture Rule: Never adopt a tool just because it trended on social media. Measure its cold start in milliseconds, verify its TypeScript schema boundary at compile time, and check what happens to your cloud bill when traffic spikes 100x.

## 2. Lesson-by-Lesson Architectural Walkthrough (5 Lessons)

Work through the lessons in sequence to build the complete system from first principles, or jump directly to the specific architectural boundary you are solving right now:

- [**Lesson 1: Running Real Postgres in the Browser with PGlite (WASM) & OPFS**](/course/local-first-web-apps-pglite-electric-sql/lesson/running-postgres-in-browser-wasm-pglite-opfs): Replaces the `NETWORK ROUND-TRIP TAX (120ms API Fetch, IndexedDB Key-Value, Offline Crash)` anti-pattern with `new PGlite('opfs://') -> OPFS File System + Web Worker Host` inside `src/db/pglite-worker.ts`. Why wait 150 milliseconds for a cloud API round-trip just to filter a table of 5,000 rows? Let's boot genuine PostgreSQL compiled to WebAssembly right inside the browser with PGlite and OPFS.
- [**Lesson 2: Reactive SQL Subscriptions with PGlite Live Queries & Multi-Tab Broadcast**](/course/local-first-web-apps-pglite-electric-sql/lesson/reactive-sql-subscriptions-pglite-live-queries-react): Replaces the `MANUAL CACHE BUSTING (Stale Tab State, Full Table Re-Fetch, Custom Event Bus)` anti-pattern with `db.live.incrementalQuery -> PGliteWorker Leader + Sub-Millisecond Diff` inside `src/hooks/useLiveTasks.ts`. Keeping multiple browser tabs and React components in sync after a local database write usually turns into event-emitter spaghetti. Let's replace manual cache invalidation with PGlite Live Queries and multi-tab worker election.
- [**Lesson 3: Streaming Cloud Postgres to the Browser with ElectricSQL Shapes**](/course/local-first-web-apps-pglite-electric-sql/lesson/real-time-postgres-sync-electricsql-shapes-pglite): Replaces the `CUSTOM WEBSOCKET GLUE (Bespoke Sync Server, Dropped Socket Gaps, No CDN Caching)` anti-pattern with `Electric HTTP Shapes -> Offset Cursor Resume + pg.electricSync()` inside `src/db/sync-shapes.ts`. Writing your own real-time sync engine between cloud Postgres and the browser is a notorious distributed-systems trap. Let's stream filtered subsets of cloud Postgres directly into PGlite using ElectricSQL Shapes.
- [**Lesson 4: The Local-First Write Path: Optimistic Outbox, Rollbacks & Conflict Resolution**](/course/local-first-web-apps-pglite-electric-sql/lesson/local-first-write-path-optimistic-outbox-conflict-resolution): Replaces the `NAIVE OPTIMISTIC UI (Ghost Writes, Server Rejects, Race Conditions)` anti-pattern with `Local Shadow + Outbox -> Persisted Mutation Queue + Deterministic Rebase` inside `src/db/outbox-mutator.ts`. Read-path sync is easy, but what happens when a user edits ten records offline, closes their laptop, and reconnects hours later? Let's engineer a rock-solid Local-First write path with a durable OPFS outbox.
- [**Lesson 5: Zero-Backend Hybrid Search in the Browser with PGlite pgvector & Full-Text RRF**](/course/local-first-web-apps-pglite-electric-sql/lesson/in-browser-hybrid-search-pglite-pgvector-fts): Replaces the `CLOUD VECTOR TAX ($200/mo Vector DB, Privacy Leakage, Keyword Blindness)` anti-pattern with `pgvector + tsvector -> HNSW Cosine Index + BM25 + Semantic RRF` inside `src/db/hybrid-search.sql`. You don't need a two-hundred-dollar-a-month cloud vector database to give users semantic search over their workspace. Let's combine PGlite's built-in pgvector extension with Postgres full-text search using Reciprocal Rank Fusion right inside the browser.

## 3. Alex's 2026 Ecosystem & Architectural Tier List

Before writing a single line of configuration, you need to know how the available platforms and patterns stack up in real production environments. Here is how I rank the ecosystem from S-Tier (our default production choice on CodingCat.dev) down to D-Tier anti-patterns to avoid:

Real PostgreSQL + pgvector running inside OPFS at 0.3ms query latency feels like magic! 🐾TIER LIST

### Alex's 2026 Local-First Database & Sync Engine Tier List

Evaluating client-side persistence, sync latency, relational query power, and offline resilience for modern web apps.

SPurrfect1 pick

#### [PGlite (OPFS Web Worker) + ElectricSQL HTTP Shape Sync + Drizzle ORM ↗](https://pglite.dev/docs/)

Local-First Relational Postgres Stack

Runs genuine PostgreSQL and pgvector inside a Web Worker backed by OPFS, streams tenant-scoped deltas via HTTP Shapes, and updates React UI in under 1 millisecond.

Read Latency:0.2ms to 0.5ms local WASM executionOffline Support:Transactional outbox + idempotent replayVector Search:Built-in pgvector (<=> cosine distance)AStrong Pick1 pick

#### [Cloudflare D1 Read Replication + TanStack Query Optimistic Updates ↗](https://developers.cloudflare.com/d1/)

Edge-First SQLite Architecture

Ideal when you want zero client WASM download size while still achieving 5ms-15ms edge SQLite reads and optimistic UI mutations.

Client Bundle:0 KB database engine downloadRead Latency:5ms to 20ms at nearest Cloudflare PoPBSolid w/ Caveats1 pick

#### [Raw IndexedDB Object Stores with Manual Event Listeners ↗](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)

Low-Level Browser Key-Value API

Built into every browser, but lacks relational JOINs, full-text search, vector similarity, and reactive query subscriptions.

Query Ergonomics:Verbose cursor callbacksCSituational0 picksNo platforms currently in C-Tier (Niche Fit, Early Preview, or Steep Quotas)DPass / Caution1 pick

#### Blocking 300ms Cloud REST Round-Trips on Every Keystroke or Checkbox Toggle

Spinner-Heavy Legacy Anti-Pattern

Forces users to stare at loading spinners on every interaction and loses unsaved work whenever Wi-Fi drops on a plane or train.

Fix:Write to local OPFS outbox first and sync in backgroundS: PurrfectA: Production ReadyB: Solid w/ CaveatsC: SituationalD: PassClick AJ to celebrate! 🐾

## 4. Production Starter Configuration & Local Setup

To follow along with the code examples in **Local-First Web Apps: PGlite (WASM Postgres) & Real-Time Sync**, start with this baseline `src/db/local-pglite.ts` configuration. It enables strict TypeScript verification, observability tracing, and local development bindings that match production 1-to-1:

Copied! 🐾📄 src/db/local-pglite.tstypescript

```
import { PGlite } from "@electric-sql/pglite";
import { live } from "@electric-sql/pglite/live";
import { vector } from "@electric-sql/pglite/vector";

export const localPg = await PGlite.create({
  dataDir: "opfs-ahp://codingcat-local-pg",
  extensions: { live, vector },
});
```

## 5. Course-Wide Production Trade-Off Matrix

Every architectural decision involves trade-offs. Use this reference table during design reviews with your team to justify why we choose edge-native TypeScript, explicit schema validation, and deterministic workflows over legacy alternatives:

Architectural Dimension2026 CodingCat.dev Course PatternLegacy Industry DefaultProduction Impact at ScaleCompute & Cold StartsV8 Isolates / Native Browser Compositor (< 5ms)Heavy Container VMs / Main-Thread JS Bloat (500ms+)Eliminates tail-latency spikes on every request and interaction.Contract & Type SafetyEnd-to-End TypeScript + Zod / GROQ TypeGenUntyped JSON payloads & manual interface driftCatches breaking schema changes in CI before deployment.State & Database TopologyCloudflare D1 Batch / Durable SQLite / Sanity Content LakeExhausted TCP pools & unindexed N+1 loopsPredictable sub-10ms reads with zero connection pool errors.Security & Multi-TenancyOAuth 2.1 PKCE + Better-Auth Scoped SessionsShared static API keys & unescaped DOM stringsZero-trust tenant isolation and $0 per-MAU SaaS tax.AI & Agent ReadinessStreamable HTTP MCP + WebMCP + RFC 9727 + Daily Spend Caps20k-token headless DOM scraping & uncapped retry loopsCuts token spend by 95%+ while preventing runaway bills.

## 6. Official Specifications, Docs & Related CodingCat.dev Deep Dives

Bookmark these official specifications and related [CodingCat.dev Courses](/courses), [Blog Posts](/blog), and [Podcast Episodes](/podcasts) as you work through the lessons:

- [**Course: The Odin Project 7: Relational Databases, SQL Indexing & Drizzle ORM**](/course/odin-databases-and-sql): Master relational normalization, B-Tree indexes, and Drizzle ORM schema design.
- [**Course: TanStack Start, Router & Drizzle ORM: Type-Safe Full-Stack React**](/course/tanstack-start-type-safe-full-stack-react): Combine local-first PGlite reactivity with type-safe TanStack Router views.
- [**Course: Hybrid Web AI Architecture (Prompt API, WebGPU, Firebase & Workers)**](/course/hybrid-web-ai-gemini-nano-firebase-workers): Pair in-browser pgvector semantic search with local WebGPU embeddings.
- [**Blog Post: Hybrid Web AI Routing with Local Browser Inference**](/post/hybrid-web-ai-routing-gemini-nano-firebase-ai-logic-workers): How to run zero-cost local AI models alongside edge fallback routes.
- [**Podcast Episode: Firebase SQL with Data Connect**](/podcast/firebase-sql-with-data-connect): Why relational PostgreSQL schemas and vector extensions dominate modern app architectures.
- [**PGlite by ElectricSQL: Official WebAssembly Postgres Documentation**](https://pglite.dev/docs/): Running real PostgreSQL 17 and pgvector in the browser with OPFS persistence.
- [**ElectricSQL HTTP Shape Sync Engine Documentation**](https://electric-sql.com/docs/intro): Streaming partial Postgres logical replication Shapes into local clients over HTTP.
- [**MDN Web Docs: Origin Private File System (OPFS) API**](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API/Origin_private_file_system): High-performance synchronous file access inside Web Workers for local SQLite and Postgres.
- [**pgvector Official GitHub Repository & HNSW Indexing Guide**](https://github.com/pgvector/pgvector): Exact and approximate nearest-neighbor cosine similarity search inside PostgreSQL.

Ready to write code? Jump straight into [**Lesson 1: Running Real Postgres in the Browser with PGlite (WASM) & OPFS →**](/course/local-first-web-apps-pglite-electric-sql/lesson/running-postgres-in-browser-wasm-pglite-opfs)

✏️ Visual Architecture Diagram

## how this course connects together.

Follow AJ from first principles to production-ready architecture.

Let’s build it!✏️ Visual Diagram: Local-First Web Apps: PGlite (WASM Postgres) & R…✓ Good PatternVISUAL DIAGRAM[Diagram Walkthrough]Step-by-step diagram breakdown for Local-First Web Apps: PGlite (WASM Postgres) & Real-Time Sync: start with Core Architecture & Production Implementation, implement Hands-On Implementation, and ship to production.AAA Contrast Verified

## related deep dives.

[View All&rarr;](/blog)[![The Odin Project 7: Relational Databases, SQL Indexing & Drizzle ORM](https://cdn.sanity.io/images/hfh83o0w/production/7221b834f72684badf77c4365f36061506da9181-1376x768.png?w=1376&q=82&fit=max&auto=format)](/course/odin-databases-and-sql)November 4, 2026[![](/logos/tags/sql-symbol-light.svg)![](/logos/tags/sql-symbol-dark.svg)SQL](/topic/sql)[![](/logos/tags/cloudflare-symbol-light.svg)![](/logos/tags/cloudflare-symbol-dark.svg)Cloudflare](/topic/cloudflare)[![](/logos/tags/typescript-symbol-light.svg)![](/logos/tags/typescript-symbol-dark.svg)TypeScript](/topic/typescript)[+1](/course/odin-databases-and-sql)

### [The Odin Project 7: Relational Databases, SQL Indexing & Drizzle ORM](/course/odin-databases-and-sql)

Master relational schema normalization, Primary/Foreign keys, INNER/LEFT JOINs, B-Tree composite indexes, ACID transactions, and type-safe Drizzle ORM on Cloudflare D1.

[![Alex Patterson](https://cdn.sanity.io/media-libraries/mlttp0BZbCpV/images/a606dfaa381aab08ddbe16a33fe1d3e1fb37c927-400x400.jpg?w=96&h=96&q=82&fit=max&auto=format)Alex Patterson](/author/alex-patterson)[![The Zero-Cold-Start Edge Stack: Astro 7, Cloudflare Workers, D1 & Better-Auth](https://cdn.sanity.io/images/hfh83o0w/production/94b403ef9d9346a601d9b16dac4ac9b8af095288-1376x768.png?w=1376&q=82&fit=max&auto=format)](/course/zero-cold-start-edge-stack)November 1, 2026[![](/logos/tags/astro-symbol-light.svg)![](/logos/tags/astro-symbol-dark.svg)Astro](/topic/astro)[![](/logos/tags/cloudflare-symbol-light.svg)![](/logos/tags/cloudflare-symbol-dark.svg)Cloudflare](/topic/cloudflare)[![](/logos/tags/sql-symbol-light.svg)![](/logos/tags/sql-symbol-dark.svg)SQL](/topic/sql)[+2](/course/zero-cold-start-edge-stack)

### [The Zero-Cold-Start Edge Stack: Astro 7, Cloudflare Workers, D1 & Better-Auth](/course/zero-cold-start-edge-stack)

Ship sub-10ms full-stack TypeScript web applications at the edge using Astro 7 Server Islands, Cloudflare Workers V8 Isolates, Cloudflare D1 SQLite, and self-hosted Better-Auth.

[![Alex Patterson](https://cdn.sanity.io/media-libraries/mlttp0BZbCpV/images/a606dfaa381aab08ddbe16a33fe1d3e1fb37c927-400x400.jpg?w=96&h=96&q=82&fit=max&auto=format)Alex Patterson](/author/alex-patterson)