Skip to content

Single-Tenant Architecture

Pocket Kit is architected around strict single-tenant process isolation and zero shared memory.

Every database instance runs as an independent operating system process with dedicated memory space, filesystem sandboxing, and its own SQLite database engine.


1. Global Request Ingress & Isolation Topology

The following diagram illustrates how inbound client traffic is routed from the edge network through TLS termination to isolated tenant runtimes:

flowchart TD
    Client["🌐 Public Internet Client<br/>(Web App / Mobile SDK / AI Agent / API Consumer)"]
    
    subgraph IngressLayer ["Automated Ingress & Security Layer (Caddy 2)"]
        Proxy["⚡ Edge Reverse Proxy & TLS Termination<br/>(Dynamic Route Engine on Port 443)"]
    end

    subgraph TenantA ["Tenant A Process (PID 1042)"]
        PB_A["PocketBase Go Engine A<br/>(127.0.0.1:8091)"]
        DB_A[("SQLite Database A<br/>(data.db in WAL mode)")]
        JS_A["Goja JSVM Sandbox A<br/>(pb_hooks / pb_migrations)"]
        PB_A --> DB_A
        PB_A --> JS_A
    end

    subgraph TenantB ["Tenant B Process (PID 1088)"]
        PB_B["PocketBase Go Engine B<br/>(127.0.0.1:8092)"]
        DB_B[("SQLite Database B<br/>(data.db in WAL mode)")]
        JS_B["Goja JSVM Sandbox B<br/>(pb_hooks / pb_migrations)"]
        PB_B --> DB_B
        PB_B --> JS_B
    end

    subgraph StaticDocs ["Documentation Ingress"]
        DocsSite["Static Astro Starlight<br/>(docs.pocket-kit...)"]
    end

    Client -->|"HTTPS / Port 443"| Proxy
    Proxy -->|"Host: app-alpha.pocket-kit..."| PB_A
    Proxy -->|"Host: app-beta.pocket-kit..."| PB_B
    Proxy -->|"Host: docs.pocket-kit..."| DocsSite

2. Multi-Tenant vs Single-Tenant Comparison

flowchart LR
    subgraph MultiTenant ["Traditional Shared Multi-Tenant Cloud"]
        SharedDB[("Shared DB Engine<br/>(Postgres / MySQL)")]
        T1_Row["Tenant A Records"]
        T2_Row["Tenant B Records"]
        SharedDB --> T1_Row
        SharedDB --> T2_Row
        Risk["⚠️ Risk of Cross-Tenant Leaks & 'Noisy Neighbors'"]
    end

    subgraph SingleTenant ["Pocket Kit Single-Tenant Model"]
        subgraph TA ["Tenant A"]
            ProcA["Dedicated Process A"]
            FileA[("Dedicated SQLite File A")]
            ProcA --> FileA
        end
        subgraph TB ["Tenant B"]
            ProcB["Dedicated Process B"]
            FileB[("Dedicated SQLite File B")]
            ProcB --> FileB
        end
        Safe["🔒 Hard OS Memory & Process Isolation"]
    end

3. SQLite Concurrency (WAL Mode)

Pocket Kit configures all tenant instances with SQLite Write-Ahead Logging (WAL):

flowchart LR
    R1["Inbound Read Query 1"] --> Reader1["SQLite Reader 1"]
    R2["Inbound Read Query 2"] --> Reader2["SQLite Reader 2"]
    
    Reader1 --> DB_Read[("Read from data.db & WAL Journal")]
    Reader2 --> DB_Read

    W1["Inbound Write Action"] --> Writer["Dedicated Sequential Writer"]
    Writer --> WAL_Append[("Append to data.db-wal")]
  • Non-Blocking Concurrent Reads: Unlimited simultaneous readers never block incoming writes.
  • Instant Commits: Write transactions write sequentially to the -wal journal file.
  • Zero Corruption Risk: System restarts automatically replay the WAL journal safely.