Diagram showing the architecture of the system

Architecture

High-Level Design

Diagram showing the Bun core architecture

Key Components

API Gateway (Hono)

Entry point for all client requests. Handles cross-cutting concerns:
  • Rate Limiting — Sliding window per user/IP
  • Idempotency — Safe retries with Idempotency-Key header
  • i18n — Locale detection + translation
  • Logging — Request/response tracking

Application Layer

Use cases implementing business logic. Each use case:
  • Has single responsibility
  • Depends on domain interfaces (ports), not implementations
  • Returns pure domain objects

Domain Layer

Pure TypeScript with no external dependencies:
  • Entities — Objects with identity (User, Session, Message)
  • Value Objects — Immutable objects (Email, UserId)
  • Domain Events — State changes (UserCreated, SessionStarted)

Infrastructure Layer

Adapters implementing application ports:
  • PostgreSQL — Persistence via Drizzle ORM (Better Auth manages auth schema)
  • BunRedis — Cache with in-memory fallback
  • File System — i18n JSON files

Design Principles

PrincipleApplication
HexagonalCore business logic isolated from infrastructure
DRYShared code in packages/
Fail-FastEarly validation in domain layer
Explicit over ImplicitNo magic — clear data flow

Data Flow

1. Client Request


2. Hono Middleware (rate limit, idempotency, i18n, logging)


3. Route Handler (validates input)


4. Use Case (orchestrates domain logic)


5. Domain Entities (pure business rules)


6. Repository Port (interface)


7. Infrastructure Adapter (MongoDB)


8. Response (reverse journey back)

Key Architectural Decisions

1. Monolith Over Microservices

The Bun Core Platform is a monolith (single deployable unit). This is intentional:
  • Simplicity — One server to deploy, monitor, debug
  • Co-location — No network latency between modules
  • Transactions — ACID across modules without distributed coordination
  • MVP speed — Faster to build and iterate
When to split later: If a module (e.g., gateway) needs independent scaling or different deployment cycles.

2. ACP WebSocket as Client

The gateway module connects to OpenClaw as a client, not a server:
  • Single WebSocket per agent (multiplexed sessions)
  • JSON-RPC 2.0 message framing over WebSocket
  • Async iterable for streaming responses
// Per-agent connection management
const connections = new Map<string, WebSocket>();

function getOrCreateConnection(agentId: string): WebSocket {
  if (!connections.has(agentId)) {
    const ws = new WebSocket(OPENCLAW_ENDPOINT, {
      headers: { 'Authorization': `Bearer ${OPENCLAW_TOKEN}` },
    });
    connections.set(agentId, ws);
  }
  return connections.get(agentId)!;
}

3. BunSQLite for Sessions (Zero Infra)

Session storage uses BunSQLite instead of MongoDB:
  • Zero infrastructure — embedded SQLite file
  • Fast for session workloads (key-value + history)
  • TTL-based expiration for old sessions
  • Falls back to Redis if configured for distributed setups

Gateway Prompt Flow (SSE)

1. POST /api/v1/gateway/prompt { agentId, userId, message }


2. SendPromptUseCase.execute()

         ├── Get or create GatewaySession
         │   └── BunSQLiteSessionStore

         ├── Get ACP adapter for agentId
         │   └── OpenClawAdapter (WebSocket client)

         ├── Send session/prompt over WebSocket
         │   └── { jsonrpc: "2.0", method: "session/prompt", ... }

         └── Stream chunks via AsyncIterable

              ├── Yield text chunks → SSE
              ├── Yield tool calls → SSE
              └── Yield done → SSE


3. SSE Response to Client
   event: chunk
   data: {"type":"text","content":"Hello"}

Performance Considerations

Cold Start

  • Bun: ~10ms cold start
  • Hono: < 1ms route matching
  • MongoDB connection pool: lazy initialization

Request Latency

Middleware stack:    ~1-2ms
Use case:            ~5-20ms (business logic)
Database:            ~5-50ms (MongoDB)
Network to OpenClaw: ~10-100ms (ACP WebSocket)
───────────────────────────────────────
Total (typical):     ~30-150ms

Security

Middleware Stack

  1. Rate Limiting — Per user/IP, sliding window
  2. Idempotency — Prevents duplicate submissions
  3. Authentication — (Upstream proxy handles, attaches userId to context)
  4. i18n — No user input in error messages
  5. Logging — Correlation IDs for audit trails

WebSocket Security

  • Token validation on connect
  • Per-session authorization via _meta.sessionKey
  • No sensitive data in WebSocket URLs

Configuration

All configuration via environment variables. See Configuration Reference.