v0.20.0
Blob-backed disks, rebuilt for object storage
Sandbox v0.20.0 makes remote blob storage feel much more like a disk: up to 308× more IOPS than v0.19.2, 5.7× more sequential write throughput, and npm installs that match the VM-local control.
The JavaScript API is unchanged. Acquire a disk, mount it, and let Sandbox own its lifecycle.
Lease acquisition
v0.19.2 already removed eager disk materialization from acquisition. v0.20 preserves that win while replacing the storage engine: the successful path is still one conditional provider write, with no disk blocks or filesystem formatting before acquire() returns.
| New R2 volume lease | Original eager path | v0.19.2 | v0.20 |
|---|---|---|---|
| Observed acquisition | 5–11 s | 348–382 ms | 377 ms median |
| Successful-path storage work | Materialize a filesystem | 1 conditional PUT | 1 conditional PUT |
The latest dedicated R2 trials ranged from 342 ms to 476 ms at p95. That keeps acquisition 13–29× faster than the original eager path and, importantly, does not give back the v0.19.2 improvement while the entire block backend changes underneath it. Acquisition time is now dominated by the provider request rather than Sandbox work.
Common I/O workloads
Live Cloudflare R2 benchmarks against the same bucket and VM:
| Workload | v0.19.2: SlateDB | v0.20: direct driver | Improvement |
|---|---|---|---|
| 4 KiB random write, QD1 | 48 IOPS | 5,842 IOPS | 121× |
| 4 KiB random write, QD32 | 256 IOPS | 78,721 IOPS | 308× |
| 4 KiB warm random read, QD32 | 3,732 IOPS | 112,798 IOPS | 30× |
| 1 MiB sequential write, QD32 | 192 MiB/s | 1,094 MiB/s | 5.7× |
These are live Cloudflare R2 results from the same bucket and VM: 4 KiB blocks for random I/O, 1 MiB blocks for sequential I/O, and the queue depths shown above. The v0.19.2 and v0.20 columns use the same benchmark shape.
The gains come from keeping ordinary filesystem traffic off the remote durability path. Explicit synchronous durability still pays object-store latency, as it should.
A real Node.js workload
Installing eslint@9.34.0 creates 1,189 files and writes about 14.3 MiB:
| Measure | Reference | v0.20 R2 disk | Result |
|---|---|---|---|
| ESLint install | 1.232 s on VM-local disk | 1.167 s | Within 5% of local; slightly faster in these trials |
| Close after workload | 8.2 s on the earlier blob path | 4.95 s | 1.7× faster |
What changed
v0.20 replaces SlateDB with a sparse block driver built directly on object storage. Writes are gathered into immutable objects and the visible disk state advances at durability boundaries. This removes the database machinery from the hot path without changing how applications acquire or mount disks.
Upgrade note
This is a new on-object volume format. Existing SlateDB-backed volumes cannot be opened by v0.20 and must be recreated or migrated separately.
Automatic garbage collection is not included yet. Failed or superseded writes may leave unreachable objects in the bucket. This does not affect the visible disk state, but long-lived deployments should account for eventual cleanup.