Durable Objects
User DO and TerminalSession DO — stateful coordination, SQLite storage, and hibernatable WebSockets.
The relay uses two Durable Object types for stateful WebSocket coordination.
User DO
One instance per email address. Handles the device-level control plane.
Responsibilities
- Device WS connections: Desktop + N mobile viewers per account
- Control message forwarding: Routes messages between desktop ↔ mobile
- WebRTC signaling: Forwards offer/answer/ICE candidates with
toClientIdtargeting - Session management: Tracks session list, handles create/delete requests
- SQLite storage: Persists device list, non-sensitive session fields, share tokens
- Rate limiting: Per-user, per-action rate limits
SQLite Schema
The User DO stores:
- Devices: ID, name, platform, online status, last heartbeat
- Sessions: ID, device ID, PTY dimensions, timestamps (no sensitive metadata)
- Share tokens: Token, session ID, permissions, expiry
Session metadata (name, CWD, processName) is never stored — it's delivered E2E encrypted via encrypted_control and only visible to authenticated clients.
Hibernation
The User DO uses Hibernatable WebSockets:
- Sleeps when no messages are flowing
- Wakes on incoming message
- Cost efficient — only billed when active
- State (SQLite) persists across hibernation cycles
Message Flow
Mobile viewer User DO Desktop
│ │ │
├── list_sessions ──────────►│─── list_sessions ────────►│
│ │ │
│◄── sessions_list ─────────│◄── sessions_list ─────────│
│ │ │
├── key_exchange_ack ───────►│─── key_exchange_ack ─────►│
│ │ (forwarded blindly) │
│ │ │
│◄── [mux binary frames] ───│◄── [mux binary frames] ──│
│ (encrypted, forwarded) │ (from desktop PTY) │TerminalSession DO
One instance per session. Handles binary terminal data relay.
Responsibilities
- Session WS connections: Desktop + N viewers per session
- Binary frame forwarding: Forwards
0xE0and0xE1encrypted frames - PTY dimensions: Tracks from plaintext
0x01resize frames (non-sensitive metadata) - Zero-knowledge: Cannot read, inspect, or store terminal content
What It Does NOT Store
- No plaintext terminal data
- No scrollback buffer
- No command history
- No session metadata (name, CWD, process)
Frame Handling
Desktop TerminalSession DO Viewers
│ │ │
├── [0xE0][encrypted] ────────►│─── [0xE0][encrypted] ───►│ (all viewers)
│ │ (forwarded blindly) │
│ │ │
│◄── [0xE0][encrypted] ───────│◄── [0xE0][encrypted] ────│ (from viewer)
│ │ (forwarded to desktop) │
│ │ │
├── [0x01][cols][rows] ────────►│ (updates internal PTY size)
│ │ │
│ [0x00] plaintext ──── REJECTED │Hibernation
The TerminalSession DO also uses Hibernatable WebSockets:
- Hibernates when no clients are connected or when idle
- Wakes on incoming WebSocket message
- Lightweight — minimal memory footprint when sleeping
Migrations
Durable Object migrations are defined in wrangler.toml:
- v1: Adds TerminalSession DO with SQLite
- v2: Adds User DO with SQLite
Cloudflare applies migrations automatically on deploy. No manual database steps required.