How the Compute Budget Works with 10 GB Workspace Storage Limits in Cloudflare Computer
The compute budget and workspace storage limits operate as independent resource constraints: the compute budget caps CPU time and RPC payload sizes (~5 MiB), while the I/O budget governs how much data can be synced per operation (~1 GB), allowing workspaces to grow to approximately 10 GB through incremental sync calls.
In the Cloudflare Computer platform, understanding how these two budgets interact is essential for building applications that handle large workspaces efficiently. This guide breaks down the technical implementation, enforcement points, and practical patterns for staying within both limits.
Understanding the Two Independent Budgets
Cloudflare Computer enforces two distinct resource boundaries that developers must navigate:
| Resource | What It Limits | Enforcement Location |
|---|---|---|
| Compute budget | CPU-time and RPC payload size between the Worker host and computerd container |
packages/computer/src/runtime/bridge.ts |
| Workspace I/O budget | Total bytes transferred during a single sync operation | packages/computer-rpc/src/sync-driver.ts |
Compute Budget: Payload and CPU Limits
The compute budget is refreshed for every request. This means a long-running script can make many incremental calls as long as each individual call stays under the payload threshold.
In packages/computer/src/runtime/bridge.ts (lines 512-516), the RPC layer enforces maxPayloadBytes:
// Bridge code truncates payloads to stay under compute budget
const maxPayloadBytes = 5 * 1024 * 1024; // ~5 MiB
// Outbound messages are automatically trimmed if they exceed this limit
This limit applies to any RPC payload traveling between the host Worker and the containerized environment. Error messages, sync chunks, and other data structures all pass through this enforcement point.
Workspace I/O Budget: Sync Transfer Limits
The I/O budget, implemented in packages/computer-rpc/src/sync-driver.ts, controls how much data moves in a single sync round. The default I/O byte budget is approximately 1 GB per sync, independent of the compute budget.
How the Budgets Interact During Sync Operations
1. Sync Push/Pull Respects I/O Byte Budget
When a workspace issues push() or pull(), the driver calls pushOnce() or pullOnce() internally. These methods serialize writes until the byte budget is exhausted:
// Conceptual flow inside the sync driver
async function pushOnce(entries: Entry[]): Promise<number> {
let bytesSent = 0;
let entriesProcessed = 0;
for (const entry of entries) {
const entryBytes = estimateSize(entry);
// Check against I/O budget (~1 GB)
if (bytesSent + entryBytes > IO_BYTE_BUDGET) {
break; // Stop and return progress; caller can issue another sync
}
// Additional check: ensure chunk fits compute payload limit
if (entryBytes > MAX_PAYLOAD_BYTES) {
// Split into smaller pieces before RPC transmission
await sendChunked(entry);
} else {
await sendOverRpc(entry);
}
bytesSent += entryBytes;
entriesProcessed++;
}
return entriesProcessed;
}
Once the I/O budget is hit, the operation returns the number of entries processed. The caller then issues another sync call. This prevents a single request from attempting to transfer terabytes of data, which would also exceed the compute payload limit.
2. RPC Payloads Must Respect Compute Budget
Every sync chunk that crosses the RPC channel passes through the bridge enforcement. The runtime/bridge.ts implementation trims error messages and other payloads to stay under maxPayloadBytes.
If a sync chunk exceeds the compute payload limit, the driver automatically splits the batch into smaller pieces before transmission. This two-layer protection ensures that:
- The I/O budget prevents unbounded memory growth during sync planning
- The compute budget prevents individual RPC failures from oversized payloads
3. Workspace Size vs. Transfer Limits
A critical distinction: workspace size limits are measured in bytes, not compute. A workspace can grow to approximately 10 GB of stored files, but the I/O budget caps how much transfers in a single sync request.
| Scenario | Compute Impact | I/O Impact |
|---|---|---|
| Many small files | Low (small payloads) | Low (under 1 GB batch) |
| Single large file | Medium (chunked transfer) | Medium (counted toward 1 GB) |
| 10 GB full workspace sync | High (many RPC calls) | Capped at 1 GB per call, requiring iteration |
Practical Code Examples
Pushing a Large Workspace Incrementally
import { Workspace } from "@cloudflare/computer";
async function pushAll(ws: Workspace): Promise<void> {
let totalPushed = 0;
let round = 0;
do {
// Each call respects both budgets automatically
const pushed = await ws.push();
totalPushed += pushed;
round++;
console.log(`Round ${round}: pushed ${pushed} entries (total: ${totalPushed})`);
// Continue until no more pending changes
} while (pushed > 0);
}
The sync driver handles chunking internally. Each push() call stays under the compute payload limit (~5 MiB) and the I/O byte budget (~1 GB).
Pulling with Budget Awareness
async function pullAll(ws: Workspace): Promise<void> {
let result;
do {
result = await ws.pull();
console.log(
`Applied ${result.applied} entries, ` +
`${result.skipped.length} read-only entries skipped`
);
// result.skipped indicates entries that couldn't be applied
// due to permissions or conflicts, not budget limits
} while (result.applied > 0 || result.skipped.length > 0);
}
Key Implementation Files
| File | Purpose |
|---|---|
packages/computer/src/runtime/bridge.ts (lines 512-516) |
Truncates RPC payloads to maxPayloadBytes |
packages/computer-rpc/src/sync-driver.ts |
Implements pushOnce()/pullOnce() with I/O byte budget enforcement |
packages/dofs/src/sync/apply.test.ts |
Verifies sync batches respect configurable byte budgets |
docs/19_performance.md |
Documents compute budget limits and I/O budgeting for workspace sync |
Performance Characteristics
According to docs/19_performance.md, you'll observe these patterns in practice:
- Fast operations: Many small files transfer quickly (low compute, low I/O)
- Slower operations: Large batches approaching the I/O budget require more RPC calls and CPU
- Predictable scaling: The ~10 GB workspace limit is achievable through iterative sync, not single-call transfer
The budget independence means you can optimize separately: reduce payload sizes for compute efficiency, or increase sync call frequency for I/O-bound workflows.
Summary
- Compute budget (~5 MiB payload, per-request CPU) is enforced in
runtime/bridge.tsand refreshed on each request - I/O byte budget (~1 GB per sync) is enforced in
sync-driver.tsviapushOnce()/pullOnce() - Workspaces can reach ~10 GB through incremental sync calls, each respecting both limits
- The driver automatically chunks data to satisfy both constraints—no manual batching required
- Independent budgets allow separate optimization for RPC efficiency vs. transfer throughput
Frequently Asked Questions
What happens if a single file exceeds the compute payload limit?
The sync driver automatically splits oversized entries into smaller chunks before RPC transmission. According to packages/computer-rpc/src/sync-driver.ts, this transparent chunking ensures individual RPC calls stay under maxPayloadBytes while the overall file still transfers correctly.
Can I adjust the I/O byte budget for my workspace?
The default ~1 GB I/O budget is configured internally. While packages/dofs/src/sync/apply.test.ts shows tests with configurable byte budgets for validation purposes, production workloads should design around the documented defaults and use iterative sync patterns rather than attempting to raise limits.
Why are compute and I/O budgets separate rather than combined?
Separation allows precise resource accounting. CPU-time and payload size affect the Worker host and computerd container directly, while I/O volume primarily impacts storage backend costs and sync latency. Independent budgets let Cloudflare optimize pricing and performance characteristics separately, as detailed in docs/19_performance.md.
How do I monitor which budget is constraining my sync?
Currently, the push() and pull() methods return entry counts, not byte metrics. For debugging, instrument your code to track cumulative entries between calls and correlate with workspace size. Frequent small batches suggest compute pressure; fewer large batches with long durations suggest I/O budget saturation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →