Skip to content

Architecture: Simple Stack, Real Integrations

5 Docker services. 12 integration points. Zero stubs.


System diagram

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#1e293b', 'primaryTextColor': '#f8fafc', 'lineColor': '#64748b', 'fontSize': '13px'}} }%%
graph TB
    subgraph CLIENT ["<b>Client</b>"]
        Browser["<b>Browser</b><br/>React + Tailwind + Vite"]
    end

    subgraph GATEWAY ["<b>Gateway</b>"]
        Nginx["<b>Nginx</b><br/>:3080"]
    end

    subgraph CORE ["<b>Application Core</b>"]
        API["<b>FastAPI</b><br/>:8000"]
        LG["<b>LangGraph</b><br/>8-node Clarifier"]
    end

    subgraph DATA ["<b>Data Layer</b>"]
        PG["<b>Postgres 16</b><br/>OLTP + metrics_catalog"]
        Redis["<b>Redis 7</b><br/>cache + pub/sub"]
    end

    subgraph AI ["<b>AI & Analytics</b>"]
        Bedrock["<b>AWS Bedrock</b><br/>Sonnet 4.6 / Opus 4.7"]
        Databricks["<b>Databricks</b><br/>SQL Warehouse"]
    end

    subgraph OBS ["<b>Observability</b>"]
        Langfuse["<b>Langfuse</b><br/>LLM tracing"]
    end

    Browser -->|"HTTP + SSE + WS"| Nginx
    Nginx --> API
    API --> LG
    API --> PG
    API --> Redis
    API --> Bedrock
    API --> Databricks
    API -.->|"opt-in"| Langfuse
    Redis -->|"pub/sub"| API
    API -->|"WebSocket"| Browser

    classDef clientNode fill:#3b82f6,stroke:#1d4ed8,color:#fff,stroke-width:2px,rx:10
    classDef gatewayNode fill:#06b6d4,stroke:#0891b2,color:#fff,stroke-width:2px,rx:10
    classDef coreNode fill:#6366f1,stroke:#4f46e5,color:#fff,stroke-width:2px,rx:10
    classDef dataNode fill:#8b5cf6,stroke:#6d28d9,color:#fff,stroke-width:2px,rx:10
    classDef aiNode fill:#f59e0b,stroke:#d97706,color:#1e293b,stroke-width:2px,rx:10
    classDef obsNode fill:#64748b,stroke:#475569,color:#fff,stroke-width:1px,rx:10,stroke-dasharray:5 5
    classDef clientBox fill:#eff6ff,stroke:#3b82f6,stroke-width:2px,color:#1e293b
    classDef gatewayBox fill:#ecfeff,stroke:#06b6d4,stroke-width:2px,color:#1e293b
    classDef coreBox fill:#eef2ff,stroke:#6366f1,stroke-width:2px,color:#1e293b
    classDef dataBox fill:#f5f3ff,stroke:#8b5cf6,stroke-width:2px,color:#1e293b
    classDef aiBox fill:#fffbeb,stroke:#f59e0b,stroke-width:2px,color:#1e293b
    classDef obsBox fill:#f8fafc,stroke:#94a3b8,stroke-width:1px,color:#64748b,stroke-dasharray:5 5

    class Browser clientNode
    class Nginx gatewayNode
    class API,LG coreNode
    class PG,Redis dataNode
    class Bedrock,Databricks aiNode
    class Langfuse obsNode
    class CLIENT clientBox
    class GATEWAY gatewayBox
    class CORE coreBox
    class DATA dataBox
    class AI aiBox
    class OBS obsBox

12 real integrations

Every integration is implemented and tested. No stubs.

# Integration What it does Evidence
Redis 7 KPI cache + pub/sub fan-out + widget data cache Real-time dashboard ticks in <5s
PostgreSQL 16 OLTP + metrics catalog + dashboard layouts Schema in db/init.sql
AWS Bedrock Two-tier LLM — 4 call sites Sonnet 4.6 (fast) + Opus 4.7 (reasoning)
Databricks Live SQL queries — 3 Asurion metrics Real claim data, not synthetic
# Integration What it does Evidence
LangGraph 8-node Clarifier with HITL pause Full state machine, streamed over SSE
SSE Streaming Clarifier progress Multi-turn conversation over POST
Docker Compose 5 services orchestrated Single make up — zero manual setup
Langfuse LLM observability — opt-in tracing Every Bedrock call traced with latency
# Integration What it does Evidence
@babel/standalone Browser-side TSX compilation Sealed scope — React + Icons only
sqlglot SQL structural safety 18 tests, 25 cases — SELECT-only enforced
:material-numeric-11-circle:{ style="color: #3b82f6" } WebSocket Real-time dashboard KPI updates Sub-second server push
:material-numeric-12-circle:{ style="color: #3b82f6" } Eval Harness LLM codegen quality gate 7 static checks + tsc --noEmit

One pattern, four protocols

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#1e293b', 'primaryTextColor': '#f8fafc', 'lineColor': '#64748b', 'fontSize': '13px'}} }%%
graph LR
    subgraph PROTOCOLS ["<b>Protocol per Purpose</b>"]
        direction TB
        REST["<b>REST</b><br/>Dashboard CRUD<br/>Widget persistence"]
        SSE["<b>SSE</b><br/>Clarifier multi-turn<br/>Streaming progress"]
        WS["<b>WebSocket</b><br/>KPI updates<br/>Sub-second push"]
        TOOL["<b>Tool-use JSON</b><br/>Bedrock calls<br/>Structured output"]
    end

    REST -->|"standard req/resp"| API2["<b>FastAPI</b>"]
    SSE -->|"streaming POST"| API2
    WS -->|"server push"| API2
    TOOL -->|"no parsing needed"| API2

    classDef restNode fill:#3b82f6,stroke:#1d4ed8,color:#fff,stroke-width:2px,rx:8
    classDef sseNode fill:#8b5cf6,stroke:#6d28d9,color:#fff,stroke-width:2px,rx:8
    classDef wsNode fill:#22c55e,stroke:#15803d,color:#fff,stroke-width:2px,rx:8
    classDef toolNode fill:#f59e0b,stroke:#d97706,color:#1e293b,stroke-width:2px,rx:8
    classDef apiNode fill:#6366f1,stroke:#4f46e5,color:#fff,stroke-width:3px,rx:10
    classDef protocolBox fill:#f8fafc,stroke:#94a3b8,stroke-width:2px,color:#1e293b

    class REST restNode
    class SSE sseNode
    class WS wsNode
    class TOOL toolNode
    class API2 apiNode
    class PROTOCOLS protocolBox

Why this matters

Each protocol is chosen for a reason — not bolted on. The same Event Context AI Action pattern works for claims, fraud, inventory, and retention. The architecture doesn't change — just the events and reason codes.


Speaker notes (45-60s)
  • Point to the system diagram: "Five Docker services. Twelve real integrations. No stubs."
  • Use the tabbed integration tables — click through Infrastructure / Application / Frontend. Don't read every row; let the count speak.
  • Emphasize the protocol diagram: "REST for CRUD, SSE for the Clarifier, WebSocket for real-time, Bedrock tool-use for structured LLM output. Each protocol chosen for a reason."
  • Land on the key line: "Same pattern works for claims, fraud, inventory, retention. The architecture doesn't change — just the events and reason codes."