JettFeaturesGalleryBlogPricing
Log inJoin waitlist
Get started
◇ Blog
Infrastructure · ArtikelPremium Blog & Interactive Reader VerificationArchitecture · ArtikelLocal-First Sync Architecture in JettAI & Pipeline · VideoIntelligent Email Processing PipelineFrontend · PodcastDesigning a Custom React Audio Player

In diesem Artikel

System Architecture FlowCore Architectural Pillars1. Persistent Local Storage2. In-Memory Thread Cache3. Change-Data-Capture (CDC) Buffer
Artikel/Architecture/2026-07-15

Local-First Sync Architecture in Jett

A deep dive into how Jett achieves high-performance email interactions using a local SQLite database, WAL mode, in-memory caching, and Supabase Realtime Change-Data-Capture (CDC) feeds.

To deliver sub-50ms user interactions, Jett relies on a hybrid local-first storage model rather than querying cloud databases directly during rendering. This architecture consists of a persistent client database, an in-memory cache, and an asynchronous CDC sync pipeline.


System Architecture Flow

Here is a visual map showing how sync events flow from the Supabase backend to the Tauri client application:

Systemübersicht

Core Architectural Pillars

1. Persistent Local Storage

We use a high-capacity SQLite database running natively in the client desktop runtime (with OPFS WASM as the web fallback). The SQLite connection is configured with optimization pragmas for safety and speed:

  • PRAGMA journal_mode = WAL; (Write-Ahead Logging for concurrent reads and writes)
  • PRAGMA synchronous = NORMAL; (Faster writes without sacrificing database integrity)
  • PRAGMA foreign_keys = ON; (Strict referential integrity)

2. In-Memory Thread Cache

ThreadHotCache is an in-memory Zustand store populated on application startup. Layout rendering modules read exclusively from this cache. This ensures the React render thread is never blocked by database calls:

// Example: Surgical cache updates
const useThreadStore = create<ThreadStore>((set) => ({
  threads: new Map(),
  patchThread: (id, updates) => set((state) => {
    const thread = state.threads.get(id);
    if (thread) {
      state.threads.set(id, { ...thread, ...updates });
    }
    return { threads: new Map(state.threads) };
  }),
}));

3. Change-Data-Capture (CDC) Buffer

Instead of reloading the layout when a Supabase Realtime event occurs, the client uses a RealtimeBuffer. This buffer accumulates and debounces sync alerts over a 100ms window. It then pulls paged metadata change batches and commits them to SQLite in atomic batches.

In diesem Artikel

System Architecture FlowCore Architectural Pillars1. Persistent Local Storage2. In-Memory Thread Cache3. Change-Data-Capture (CDC) Buffer