Skip to content

Commit 0590f6d

Browse files
Add WebSocket transport documentation
Documents the new WebSocket transport feature that enables multiplexing SDK operations over a single WebSocket connection to reduce sub-request count in Workers. Changes: - Add comprehensive WebSocket transport concept page - Document useWebSocket option in sandbox configuration - Update architecture overview to mention transport options Related PR: cloudflare/sandbox-sdk#253 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 0f1dfd7 commit 0590f6d

File tree

3 files changed

+237
-2
lines changed

3 files changed

+237
-2
lines changed

src/content/docs/sandbox/concepts/architecture.mdx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ flowchart TB
2626
DO["Sandbox Durable Object routes requests & maintains state"]
2727
Container["Isolated Ubuntu container executes untrusted code safely"]
2828
29-
DO -->|HTTP API| Container
29+
DO -->|HTTP or WebSocket| Container
3030
end
3131
3232
Worker -->|RPC call via the Durable Object stub returned by `getSandbox`| DO
@@ -91,14 +91,24 @@ When you execute a command:
9191
await sandbox.exec("python script.py");
9292
```
9393

94-
1. **Client SDK** validates parameters and sends HTTP request to Durable Object
94+
1. **Client SDK** validates parameters and sends request to Durable Object (HTTP or WebSocket)
9595
2. **Durable Object** authenticates and routes to container runtime
9696
3. **Container Runtime** validates inputs, executes command, captures output
9797
4. **Response flows back** through all layers with proper error transformation
9898

99+
### Transport options
100+
101+
The SDK supports two transport methods for communication between the Durable Object and container:
102+
103+
- **HTTP transport (default)** - Each SDK operation creates a separate HTTP request
104+
- **WebSocket transport** - Multiple operations multiplex over a single WebSocket connection
105+
106+
WebSocket transport reduces sub-request count, making it ideal for high-volume operations. Learn more in the [WebSocket Transport concept guide](/sandbox/concepts/websocket-transport/).
107+
99108
## Related resources
100109

101110
- [Sandbox lifecycle](/sandbox/concepts/sandboxes/) - How sandboxes are created and managed
102111
- [Container runtime](/sandbox/concepts/containers/) - Inside the execution environment
103112
- [Security model](/sandbox/concepts/security/) - How isolation and validation work
104113
- [Session management](/sandbox/concepts/sessions/) - Advanced state management
114+
- [WebSocket transport](/sandbox/concepts/websocket-transport/) - Reduce sub-request count with WebSocket multiplexing
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
---
2+
title: WebSocket Transport
3+
pcx_content_type: concept
4+
sidebar:
5+
order: 8
6+
description: Learn how WebSocket transport reduces sub-request usage by multiplexing SDK operations over a single persistent connection.
7+
---
8+
9+
WebSocket transport is an alternative communication method between the Sandbox SDK client and container runtime that reduces sub-request count by multiplexing multiple operations over a single WebSocket connection.
10+
11+
## Why use WebSocket transport
12+
13+
When using HTTP transport (the default), each SDK operation (like `exec()`, `readFile()`, `writeFile()`) creates a separate HTTP request. In Workers and Durable Objects, these requests count against [sub-request limits](/workers/platform/limits/#subrequests).
14+
15+
WebSocket transport solves this by:
16+
17+
- **Multiplexing requests** - Send many operations over one WebSocket connection
18+
- **Reducing sub-request count** - Only the initial WebSocket upgrade counts as a sub-request
19+
- **Maintaining compatibility** - Works with all existing SDK methods without code changes
20+
21+
## When to use WebSocket transport
22+
23+
Consider WebSocket transport when:
24+
25+
- **High operation volume** - Your Worker performs many sandbox operations per request
26+
- **Near sub-request limits** - You are approaching Workers sub-request limits
27+
- **Long-lived interactions** - Your code performs sequences of operations on the same sandbox
28+
29+
Continue using HTTP transport (default) when:
30+
31+
- **Simple use cases** - You perform only a few operations per request
32+
- **No sub-request concerns** - Your Worker is well under sub-request limits
33+
- **Maximum compatibility** - You want to use the most battle-tested transport
34+
35+
## How it works
36+
37+
### Architecture
38+
39+
```mermaid
40+
flowchart LR
41+
accTitle: WebSocket Transport Architecture
42+
accDescr: Diagram showing how multiple SDK operations multiplex over a single WebSocket connection
43+
44+
Worker["Worker (SDK Client)"]
45+
DO["Sandbox Durable Object"]
46+
Container["Container Runtime"]
47+
48+
Worker -->|"WebSocket Upgrade (1 sub-request)"| DO
49+
DO <-->|"HTTP to Container"| Container
50+
51+
Worker -.->|"exec() → WS message"| DO
52+
Worker -.->|"readFile() → WS message"| DO
53+
Worker -.->|"writeFile() → WS message"| DO
54+
55+
style Worker fill:#ffe8d1,stroke:#f6821f,stroke-width:2px
56+
style DO fill:#dce9f7,stroke:#1d8cf8,stroke-width:2px
57+
style Container fill:#d4f4e2,stroke:#17b26a,stroke-width:2px
58+
```
59+
60+
### Protocol
61+
62+
The WebSocket transport implements a request-response protocol:
63+
64+
1. **Client sends WSRequest** with unique ID, method, path, and body
65+
2. **Server sends WSResponse** with matching ID, status, and body
66+
3. **Streaming support** - For streaming operations, server sends multiple WSStreamChunk messages before final WSResponse
67+
68+
All messages are JSON-encoded. The protocol maintains compatibility with existing HTTP-based handlers - the container runtime routes WebSocket messages through the same HTTP handlers used for direct HTTP requests.
69+
70+
## Enable WebSocket transport
71+
72+
WebSocket transport is automatically available in the SDK. Enable it by passing `useWebSocket: true` when creating a sandbox:
73+
74+
```typescript
75+
import { getSandbox } from "@cloudflare/sandbox";
76+
77+
export default {
78+
async fetch(request: Request, env: Env): Promise<Response> {
79+
// Enable WebSocket transport
80+
const sandbox = getSandbox(env.Sandbox, "my-sandbox", {
81+
useWebSocket: true
82+
});
83+
84+
// All operations now use WebSocket transport
85+
await sandbox.exec("echo 'Hello via WebSocket'");
86+
await sandbox.writeFile("/workspace/data.txt", "content");
87+
const content = await sandbox.readFile("/workspace/data.txt");
88+
89+
// Only the initial WebSocket upgrade counted as a sub-request
90+
return Response.json({ success: true });
91+
}
92+
};
93+
```
94+
95+
## Performance characteristics
96+
97+
### Connection lifecycle
98+
99+
- **First operation** - Establishes WebSocket connection (counts as 1 sub-request)
100+
- **Subsequent operations** - Reuse existing connection (no additional sub-requests)
101+
- **Connection pooling** - The SDK maintains the connection for the lifetime of the sandbox instance
102+
- **Automatic reconnection** - If connection drops, SDK transparently reconnects
103+
104+
### Latency considerations
105+
106+
- **First request** - Slightly higher latency due to WebSocket upgrade handshake
107+
- **Subsequent requests** - Similar latency to HTTP transport
108+
- **Streaming operations** - WebSocket transport converts Server-Sent Events (SSE) to WebSocket messages
109+
110+
### Best practices
111+
112+
**Use WebSocket transport when:**
113+
114+
```typescript
115+
// High operation count per request
116+
const sandbox = getSandbox(env.Sandbox, "batch-processor", {
117+
useWebSocket: true
118+
});
119+
120+
for (let i = 0; i < 100; i++) {
121+
await sandbox.exec(`process-item-${i}.sh`);
122+
}
123+
// Only 1 sub-request instead of 100
124+
```
125+
126+
**Stick with HTTP transport when:**
127+
128+
```typescript
129+
// Single operation per request
130+
const sandbox = getSandbox(env.Sandbox, "simple-exec");
131+
await sandbox.exec("single-command.sh");
132+
// 1 sub-request either way, HTTP is simpler
133+
```
134+
135+
## Implementation details
136+
137+
### Message types
138+
139+
The WebSocket protocol defines four message types:
140+
141+
- **WSRequest** - Client to server request with method, path, and body
142+
- **WSResponse** - Server to client response with status and body
143+
- **WSStreamChunk** - Server to client streaming data chunk
144+
- **WSError** - Server to client error message
145+
146+
### Streaming support
147+
148+
For streaming operations like `execStream()`:
149+
150+
1. Client sends WSRequest for streaming endpoint
151+
2. Server responds with multiple WSStreamChunk messages (converted from SSE format)
152+
3. Server sends final WSResponse when stream completes
153+
154+
This maintains compatibility with existing streaming code while using WebSocket transport.
155+
156+
### Error handling
157+
158+
WebSocket transport handles errors at multiple levels:
159+
160+
- **Connection errors** - Automatic reconnection with exponential backoff
161+
- **Request errors** - Returned as WSError messages with error codes
162+
- **Timeout handling** - Configurable timeouts for connection and requests
163+
164+
## Compatibility
165+
166+
WebSocket transport is fully compatible with:
167+
168+
- All SDK methods (exec, files, processes, ports, etc.)
169+
- Streaming operations (execStream, readStream)
170+
- Session management
171+
- Preview URLs and port forwarding
172+
- Code Interpreter API
173+
174+
No code changes are required to existing SDK usage - simply enable the option and all operations transparently use WebSocket transport.
175+
176+
## Limitations
177+
178+
- **Workers and Durable Objects only** - WebSocket transport is designed for environments with sub-request limits
179+
- **Not for external services** - This is for SDK-to-container communication only, not for [WebSocket connections to services inside sandboxes](/sandbox/guides/websocket-connections/)
180+
- **Durable Object WebSocket limits apply** - Standard Durable Object WebSocket limits and quotas apply
181+
182+
## Related resources
183+
184+
- [Architecture concept](/sandbox/concepts/architecture/) - Overview of SDK architecture
185+
- [Sandbox options](/sandbox/configuration/sandbox-options/) - Configuration options for sandboxes
186+
- [Workers limits](/workers/platform/limits/) - Workers sub-request limits and quotas
187+
- [WebSocket connections to sandboxes](/sandbox/guides/websocket-connections/) - Connect to WebSocket servers inside sandboxes

src/content/docs/sandbox/configuration/sandbox-options.mdx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,44 @@ import { getSandbox } from '@cloudflare/sandbox';
1717
const sandbox = getSandbox(binding, sandboxId, options?: SandboxOptions);
1818
```
1919

20+
### useWebSocket
21+
22+
**Type**: `boolean`
23+
**Default**: `false`
24+
25+
Enable WebSocket transport to reduce sub-request count by multiplexing SDK operations over a single WebSocket connection. When enabled, all SDK operations use WebSocket messages instead of individual HTTP requests.
26+
27+
<TypeScriptExample>
28+
```ts
29+
// Enable WebSocket transport for high-volume operations
30+
const sandbox = getSandbox(env.Sandbox, 'batch-processor', {
31+
useWebSocket: true
32+
});
33+
34+
// All operations use the same WebSocket connection
35+
for (let i = 0; i < 100; i++) {
36+
await sandbox.exec(`process-item-${i}.sh`);
37+
}
38+
// Only 1 sub-request (WebSocket upgrade) instead of 100 HTTP requests
39+
```
40+
</TypeScriptExample>
41+
42+
**Benefits**:
43+
- **Reduced sub-requests** - Only the initial WebSocket upgrade counts as a sub-request
44+
- **Better for high volume** - Ideal when performing many operations per Worker request
45+
- **Transparent** - Works with all SDK methods without code changes
46+
47+
**When to use**:
48+
- Your Worker performs many sandbox operations per request
49+
- You are approaching Workers sub-request limits
50+
- You need sequences of operations on the same sandbox
51+
52+
**When not to use**:
53+
- Simple use cases with only a few operations per request
54+
- You are well under sub-request limits
55+
56+
Learn more in the [WebSocket Transport concept guide](/sandbox/concepts/websocket-transport/).
57+
2058
### keepAlive
2159

2260
**Type**: `boolean`

0 commit comments

Comments
 (0)