Pre-warmed Session Pool
Pre-create sandbox sessions so that POST /v1/sessions can return in sub-100ms (often sub-1ms in local benchmarks) when a matching session is available in the pool, instead of cold create latency.
How It Works
Daemon Startup
├─ Create N sandboxes per configured image (no workspace)
├─ Store sessions with status "pool_idle" (not subject to TTL expiry)
└─ Pool ready
User Creates Session
├─ pool.Get(image, workspace_id) → matching session available? → acquire from pool ✅
├─ Update status to "running", set TTL, return to user
├─ Refill pool in background for that key
└─ If pool empty → normal create, then refill in background
Scope: The pool supports both sessions with and without workspace_id using workspace-aware keys.
Configuration
pool:
enabled: true
images:
python: 3 # keep 3 Python sessions ready
node: 2 # keep 2 Node sessions ready
enabled(default:false): Turn pooling on. Keep disabled if you don’t need sub-100ms create latency.images: Map of image name → number of pre-warmed sessions to maintain.
Pool images are filtered by allowed_images. If allowed_images is set and an image is not in the list, it is not pooled.
Environment override: SANDKASTEN_POOL_ENABLED=true
When to Use
Pooling helps when:
- Session creation is a hot path (many sessions per second)
- Sub-100ms latency is important
- You want to hide cold-start overhead
For typical usage (~100–200ms cold create), pooling is optional.
Implementation Details
- Pool lifecycle: At daemon startup,
RefillAllcreates the configured number of sandboxes per image (workspace_id = empty). They are stored with statuspool_idleand far-future expiry so the reaper does not destroy them. - Acquire:
pool.Getreturns a session ID, which is removed from the pool. The session status is updated torunningandexpires_atis set to the user’s TTL. - Refill: After each create (pool hit or normal), a background goroutine calls
Refillto replenish the specific key (imageorimage+workspace_id). - Release: When a session is destroyed, it is not returned to the pool. The pool is replenished on demand by
Refillafter future creates.
Workspace Support
Sessions created with workspace_id can also use the pool via workspace-aware entries. The flow:
- Check pool key
(image, workspace_id) - If hit: acquire directly and return
- If miss: normal create with
workspace_id, then refill that key in background
This avoids the previous late bind-mount-on-acquire path on readonly roots and gives consistent warm behavior for shared workspaces.