Architecture
Understanding how NANO works under the hood
High-Level Architecture
NANO consists of a Rust-based runtime that embeds V8 to execute JavaScript in isolated environments.
[Client Request]
|
v
[HTTP Router] --> [App Registry]
| |
v v
[Worker Pool] <-- [Isolate Cache]
|
v
[V8 Isolate] --> [JavaScript Execution]
V8 Isolates
Each application runs in its own V8 isolate, providing complete isolation from other applications while sharing the same OS process.
Isolate Properties
- Memory limit: Configurable heap size per isolate
- Context reset: ~5ms between requests (not full recreate)
- Thread-local: Isolates never move between threads
Sliver Snapshots
Slivers enable sub-millisecond cold starts by serializing the pre-initialized V8 isolate state.
Sliver Creation Process
1. Create fresh V8 isolate 2. Load JavaScript bundle into isolate 3. Execute initialization code 4. Serialize isolate state to file 5. Compress and store as sliver Result: 267ms cold start becomes 267us
Worker Pool
The worker pool manages concurrent request handling with thread-local isolates.
Request Flow
- HTTP request arrives at router
- Router determines target app from hostname/path
- Request is queued for worker pool
- Available worker picks up request
- Worker resets isolate context (~5ms)
- JavaScript handler executes
- Response is returned to client
WebSocket Upgrade Path v2.0a
WebSocket connections use a dedicated worker thread per connection. The isolate lifetime is bound to the connection — when the connection closes, the isolate is recycled.
HTTP GET + Upgrade: websocket
|
v
detect_ws_upgrade() — router.rs
| axum 101 handshake
v
tokio relay task — WsChannels (mpsc)
| WsInbound / WsOutbound
v
TenantPool::dispatch_ws()
| lazy-spawn WS worker thread
v
JS fetch() handler (registers addEventListener)
|
v
'ws_messages loop
| recv_timeout(idle_timeout_ms) per frame
| CpuTimeoutGuard + OOM check per message
v
Close/Disconnect → break 'requests → isolate recycled
Key Properties
- One isolate per connection: Worker thread dedicated to single WS connection
- Isolate recycled on close: Fresh isolate for next connection — no state leakage
- Per-frame enforcement: CPU timeout guard and OOM check on every message
- Idle timeout: Connection closed after
ws_idle_timeout_mswith no frames (default 60s) - Max message size: 32 MiB default (
ws_max_message_bytes)