Skip to main content
InfraGap.com Logo
Home
Getting Started
Core Concept What is a CDE? How It Works Benefits CDE Assessment Getting Started Guide Inner Loop vs Outer Loop Environment Drift Local vs Cloud CDEs for Startups
AI & Automation
AI Coding Assistants Agentic AI AI-Native IDEs Agentic Engineering AI Agent Orchestration AI Governance AI-Assisted Architecture Shift-Left AI LLMOps Autonomous Development AI/ML Workloads CDEs for Data Science GPU Computing
Agent Infrastructure
Agent Experience (AX) Agent Egress Control Computer Use Agents Agent Evals Agent Runbooks Agent Client Protocol AGENTS.md MCP Servers Git Worktrees Kubernetes Agent Sandbox Agent Fleets Agent Identity Prompt Injection Defense Agent Observability Context Engineering AI Code Review Bottleneck Headless Agents in CI Spec-Driven Development Agent Readiness Code Provenance
Implementation
Architecture Patterns DevContainers Advanced DevContainers Language Quickstarts IDE Integration CI/CD Integration Platform Engineering Developer Portals Container Registry Multi-CDE Strategies Remote Dev Protocols Nix Environments Hermetic Builds OpenTofu for CDEs Kubernetes Development
Operations
Performance Optimization High Availability & DR Disaster Recovery Monitoring Capacity Planning Multi-Cluster Development Troubleshooting Runbooks Ephemeral Environments Sandbox Environments Workspace Snapshots Database Branching
Security
Security Deep Dive Zero Trust Architecture Secrets Management Vulnerability Management Network Security IAM Guide Supply Chain Security Air-Gapped Environments AI Agent Security MicroVM Isolation Compliance Guide EU AI Act Cyber Resilience Act Data Residency Governance
Planning
Pilot Program Design Stakeholder Communication Risk Management Migration Guide Cost Analysis FinOps GreenOps Vendor Evaluation Training Resources Developer Onboarding Team Structure Platform Maturity Model Open Source CDEs AI Productivity Paradox Build vs Buy DevEx Metrics Productivity Engineering Industry Guides CDEs for Healthcare CDEs for Financial Services CDEs for Government Edge Development WebAssembly in CDEs
Resources
Tools Comparison State of CDEs 2026 Isolation Decision Tool Template Library
Learning Paths
All Paths Platform Engineer Security and Compliance Engineering Manager
Vendor Reviews
GitHub Codespaces Coder Ona Google Workstations Microsoft Dev Box Okteto Eclipse Che DevPod Daytona E2B
Head to Head
Coder vs Codespaces Coder vs Ona Ona vs Codespaces Coder vs Okteto Self-Hosted vs Managed E2B vs Daytona CDE Market Guide CDE vs Alternatives Case Studies Lessons Learned Glossary FAQ Sources & Citations

Workspace Snapshots, Forking and Cold Start Performance

Checkpoint and restore, memory snapshots, warm pools and fork-on-demand. What the techniques actually do, and how to read the provisioning numbers platforms publish.

Cold Start Became a Product Constraint

Provisioning latency used to be paid once a morning. Now it is paid per task.

When a developer opened one cloud workspace at the start of the day and kept it until evening, a two-minute provision was an irrelevance amortized over eight hours. That assumption is what has broken. Environments are now created per pull request, per review, and per agent attempt, and the same two minutes is charged against a task that may itself only take ninety seconds of useful work. Startup cost stops being an operational detail and becomes the thing that decides whether an entire workflow is viable.

It helps to be precise about what a cold start is made of, because each technique here attacks a different part of it. Scheduling and node acquisition come first, and provisioning a new node dominates everything else. Then image pull, a function of layer size and cache locality. Then filesystem setup and volume attachment, then the repository clone, then dependency installation and build or index warm-up, and only then is the process running and initialized. A technique that removes the last four steps but not the first two has a floor it cannot go below.

That last stage is the one people underestimate. Modal, describing its memory snapshot feature, notes that importing a single large Python library, torch, "executes 26,000 syscalls" - work a container redoes on every cold start even though the result is identical every time. Capturing the state after that work and replaying it attacks a genuinely large constant.

The Ladder of Techniques

TechniqueWhat it removesWhat it still paysMain cost
Image and layer cachingMost of the pull, when the node already has the layersScheduling, clone, install, initNode-local disk, cache management
Prebuilds and cached workspace disksClone and dependency installationScheduling, pull, process initPrebuild compute, and staleness against the branch
Warm poolsEverything up to allocation, if the pool is deep enoughPer-session personalization, and a full cold start on a pool missIdle capacity billed continuously
Filesystem snapshotsDisk setup and installed stateProcess start and in-memory initializationSnapshot storage, and drift from the source of truth
Memory snapshots and checkpoint/restoreProcess init, imports, JIT and cache warm-upRestoring the snapshot itself, plus schedulingLarge snapshot images; anything not capturable is excluded
Fork on demandAll shared setup across N parallel variantsPer-fork divergence and cleanupCorrectness: forks share identity and state they should not

Checkpoint and Restore

Freezing a running process to disk, and the reasons it is harder than it sounds

The foundational tool is CRIU, Checkpoint and Restore in Userspace. Its own description is the clearest one available: "you can freeze a running application (or part of it) and checkpoint it to a hard drive as a collection of files. You can then use the files to restore and run the application from the point it was frozen at." It is not new or exotic, and the project notes it "is currently used by (integrated into) OpenVZ, LXC/LXD, Docker, and other software."

Kubernetes exposes this through the kubelet checkpoint API, gated behind the ContainerCheckpoint feature gate, which the documentation records as beta and enabled by default since Kubernetes v1.30. The checkpoint is written as a tar archive under the kubelet's checkpoint directory on the node. That documentation also contains the single most important warning about this whole family of techniques, and it deserves quoting in full: "Typically a checkpoint contains all memory pages of all processes in the checkpointed container. This means that everything that used to be in memory is now available on the local disk. This includes all private data and possibly keys used for encryption."

Read that as a design constraint rather than a footnote. A snapshot is an unencrypted copy of everything the process held in memory: tokens fetched at startup, decrypted secrets, connection credentials, and whatever the last agent session happened to read. Snapshot storage therefore inherits the classification of the most sensitive thing the workspace ever touched, and a snapshot that is reused across sessions or across tenants is a data-sharing decision. The access controls that matter for secrets management apply to the snapshot store too.

Firecracker MicroVM Snapshots

At the virtual machine layer, Firecracker describes snapshotting as a mechanism "through which a running microVM and its resources can be serialized and saved to an external medium", capturing guest memory and the emulated hardware state. Its documentation notes that diff snapshot support is in developer preview, and it publishes no restore-latency figure, saying only that create and resume performance depends on memory size, vCPU count and device count.

The number people quote for Firecracker is a different one and is worth stating precisely. Its specification commits that "It takes <= 125 ms to go from receiving the Firecracker InstanceStart API call to the start of the Linux guest user-space /sbin/init process." That is a boot guarantee up to init, not a measure of when a workload is ready to serve, and the gap between those two points is usually where your actual startup cost lives. More on the isolation layer itself is on microVM isolation.

GKE Pod Snapshots for Agent Sandboxes

Google documents Pod snapshots for its Agent Sandbox, and is unusually specific about scope. The snapshot captures "the entirety of application state: all open file descriptors, threads, CPU registers, and memory", plus the container root filesystem, EmptyDir volumes and tmpfs mounts, and loopback, listening and Unix-domain sockets. It excludes persistent volumes, external network connections, and firewall rules.

The constraints are equally specific and will decide whether this is available to you at all. It requires GKE Sandbox with gVisor. It "doesn't support E2 machine types", the how-to's tutorial uses N2 machines instead, TPUs are unsupported, and GPU support is limited, with multi-GPU only on L4 and no Multi-Instance GPU. There is also a minimum GKE version floor, and note that Google's own how-to and concepts pages state slightly different floors, so check the specific page for the path you are following. Google publishes no restore-time figure. The CRD model around it is covered on Kubernetes agent sandbox.

Memory Snapshots in Practice

The one platform that publishes numbers, and exactly what those numbers cover

Modal's write-up of its memory snapshot feature is the most useful published account of this technique, because it states both the mechanism and the figures. It describes capturing "the entire state of a Linux container right before it was about to accept a request", specifically "the container's filesystem mutations and its entire process tree", with "the notable exception of live network connections and NVIDIA GPU state" (Modal, January 2025).

The figures it publishes are these, and all of them are the vendor measuring its own platform on its own workloads rather than an independent benchmark. Generally, "memory snapshot restore is about 2.5x faster than a standard container startup". For one specific workload, "a Stable Diffusion inference Function that takes around 13 seconds normally restores in only 3.5 seconds". And for the library import mentioned earlier, importing torch "takes normally around 5 seconds to cold start. With snapshot restore it's around 1.05 seconds at p50 and 0.69 seconds at p0".

Two things make these numbers worth engaging with rather than dismissing. They are attached to named workloads rather than to an abstract "cold start", and they include a percentile rather than a single best case. The exclusions are the part to plan around: live network connections and GPU state are not captured, so anything holding an open database connection, a leased credential, or an initialized GPU context has to re-establish it after restore. That reconnection work is real, it happens after the snapshot restores, and it is not inside the quoted number.

What a Snapshot Silently Preserves

Restoring the same snapshot many times means every restored instance starts with an identical view of the world, and some of that view is supposed to be unique. Process identifiers, hostnames, random seeds drawn at startup, cached DNS results, session tokens, and any identifier generated during initialization are all frozen into the image. This is the mirror image of the reproducibility argument on hermetic builds: there, identical outputs from identical inputs is the goal; here, identical output from what is supposed to be a fresh instance is a bug. Anything that must be unique per session has to be generated after restore, not before the snapshot is taken.

Warm Pools

The technique that works by not solving the problem, and paying for that instead

A warm pool does not make provisioning fast. It moves provisioning off the request path by doing it in advance and holding the result. That is a straightforward trade of money for latency, and its honesty is a virtue: there is no mechanism to misunderstand, only a pool depth to choose. The failure mode is equally simple. When arrivals exceed pool depth, the surplus requests pay the full cold start, so a pool tuned to the average is a pool that fails exactly during the bursts you built it for.

The Kubernetes agent-sandbox project makes this a first-class cluster object. SandboxWarmPool lives in the extensions API group and is deliberately small: a replica count, a reference to the template being pre-warmed, and an update strategy for how existing warm instances are replaced when that template changes. It carries the scale subresource, so a HorizontalPodAutoscaler can drive pool depth from a metric rather than from a hard-coded number.

A SandboxWarmPool

apiVersion: extensions.agents.x-k8s.io/v1beta1
kind: SandboxWarmPool
metadata:
  name: python-sdk-warmpool
  namespace: agent-sandboxes
spec:
  replicas: 10
  sandboxTemplateRef:
    name: python-sandbox-template
  # Recreate replaces warm instances immediately when the template changes.
  # OnReplenish (the default) lets existing warm instances drain first.
  updateStrategy:
    type: Recreate

The update strategy is the field worth thinking about. A warm pool is a cache of a template, and like every cache it can serve something stale. Choosing to drain rather than recreate means a session can be handed a sandbox built from the previous image, which is the same class of problem as a prebuild that is out of date relative to the branch. Confirm the field names against the CRDs shipped with the release you install; this API is young and still moving.

A Published Example: Stripe's Devboxes

Stripe has written publicly about applying this to development machines for its coding agents. In its own words: "To achieve this 'hot and ready' standard, we proactively provision and warm up a pool of devboxes so they are ready when a developer wants them." The post describes the target rather than a measured result, and the distinction matters: "We want it to feel effortless to spin up a new devbox, so we aim for it to be ready within 10 seconds" (Stripe, February 2026).

The more instructive part is what the warming actually consists of. Stripe lists "cloning gigantic git repositories, warming Bazel and type checking caches, starting code generation services that continually run on devboxes, and more", after which the developer gets a box already checked out to a recent copy of the main branch across the company's main repositories. That is the real lesson for anyone sizing this work: the expensive part of a warm workspace is rarely the container. It is the repository, the build cache and the language server index, which is precisely why a cacheable build and a fast provisioning story turn out to be the same project.

Depth Is a Budget Decision

Warm capacity bills continuously whether or not anything claims it. Pool depth is therefore not a tuning parameter owned by an engineer, it is a spend commitment, and it should be reviewed like one. See FinOps.

Size to the Burst, Not the Mean

Agent-driven arrivals are bursty by construction, because one human decision can fan out into many sessions at once. A pool sized to average demand is empty during exactly the events that motivated it. Capacity planning covers the arrival modeling.

Measure the Miss Rate

The number that tells you whether a pool is working is not average allocation latency, which a mostly-hitting pool flatters. It is the proportion of requests that missed and the latency those requests actually saw.

Fork on Demand

One warm workspace, many divergent continuations

Forking generalizes the snapshot from a restore mechanism into a branching one. Instead of restoring a snapshot once, you restore it many times to create workspaces that share every byte of setup and then diverge. That maps exactly onto how agents are used: bring one workspace to the point where the repository is cloned, dependencies are installed and the build cache is warm, then fork it once per candidate approach. The expensive prefix is paid once instead of N times. It is the same economic argument as copy-on-write database branching, applied to the whole machine rather than one datastore.

The correctness problems follow directly from what a snapshot preserves. Every fork inherits the same in-memory state: the same random seeds, the same cached identity, the same open descriptors, the same idea of its own hostname. Anything derived from those is now shared across siblings that believe they are independent. External resources are worse, because a snapshot taken while holding a lease, a lock or a queue subscription produces N processes that all think they hold something exactly one of them can hold.

Safe to Fork

  • A cloned repository at a known commit
  • Installed dependencies and a populated build cache
  • A warm language server index
  • Loaded libraries and completed interpreter startup

Re-establish After the Fork

  • Network connections, which snapshots do not carry anyway
  • Credentials, leases and anything with a TTL
  • Workspace identity: hostname, instance ID, random seed
  • Any external resource held exclusively

The practical rule is to take the snapshot at a boundary you choose rather than at an arbitrary moment: bring the workspace to a defined ready state, close everything external, snapshot, and treat re-establishment as an explicit post-restore step. A snapshot taken opportunistically from a running session will preserve whatever it happened to be holding.

How to Read a Published Cold-Start Number

Every figure below is the vendor's own claim about its own product. None has been independently reproduced here.

PlatformPublished claimWhat it does not say
Daytona"Sub 90ms sandbox creation from code to execution"Whether the image was already resident, which region, and what percentile
E2BIts site states both 80 ms and "less than 200 ms" for same-region sandbox startWhich of the two is current. The docs publish no figure at all
ModalMemory snapshot restore "about 2.5x faster than a standard container startup"A relative figure, so it depends entirely on how slow the baseline was
GKE Agent SandboxWarm pools serve sandboxes faster than standard Pod scheduling allows, "typically <1s"Nothing published on snapshot restore time
GitHub CodespacesNo startup figure. Only a decision threshold: prebuilds likely help if creation currently exceeds two minutesThat threshold is guidance for choosing prebuilds, not a measured cold start
CoderDocuments prebuilt workspaces as an automatically maintained pool, with no numberNothing, which is at least an honest position

Four Questions to Ask of Any Figure

  • Measured to what point? Process start, API returning, or ready to serve a request are three very different moments.
  • From what state? A warm pool hit, a cached image, or a genuinely cold node are not the same measurement.
  • Which percentile? A median cold start says nothing about the tail, and the tail is what users notice.
  • Whose workload? Numbers are almost always from a minimal sandbox, not from your repository and your dependency tree.

A Cautionary Note on Vendor Continuity

Fast provisioning is a headline feature in a category that is still consolidating, and the headline can outlive the product it described. Daytona is the clearest illustration. It began as a cloud development environment company, then publicly announced in April 2025 that it had "decided to realign its focus from solving developer environment inconsistencies for humans to solving runtimes for AI agents", with the internal shift dating to around the turn of that year.

Its widely starred public repository now carries a notice that it "is no longer maintained", stating that as of June 2026 core development moved to a private codebase and the repository will receive no further updates or releases. The commercial product continues to ship. The open-source one that many evaluations were based on does not. When a provisioning number is load-bearing for your architecture, check what is behind it as carefully as the number itself, using the framework on vendor evaluation.

What Idle Time Costs

An agent waiting on a model response is idle, and whether you pay for that is a billing-model question

Agent workloads have an unusual duty cycle. A session spends much of its wall-clock life waiting: for a model response, a build, a test suite, a human review. Under conventional per-instance billing all of that is charged at full rate, which is what makes warm pools and long-lived sessions expensive in a way that traditional service workloads are not.

Some platforms bill the waiting differently, and Cloudflare's model is the clearest published example. Its Workers documentation states that "CPU time measures how long the CPU spends executing your Worker code" and that "waiting on network requests (such as fetch() calls, KV reads, or database queries) does not count toward CPU time". Note the precise term: this is CPU time versus wall time, not a product called "active CPU".

The important asymmetry appears when you move up to containers. Cloudflare's container pricing states that "CPU usage is based on active usage only", but that "memory and disk usage are based on the provisioned resources". A container waiting on a model response stops accruing CPU charges and keeps accruing memory and disk charges for the whole time it is awake. That is a materially better shape than paying for everything, and it is not free idling. Any capacity model that assumes idle costs nothing will under-forecast.

Snapshot Instead of Holding

A session blocked on a human for an hour does not need to hold compute. Snapshotting and restoring later converts held capacity into stored state, and storage is almost always the cheaper of the two.

Snapshots Are Not Free Either

A memory snapshot is roughly the size of the memory it captured, so a fleet of them is a real storage line item with a real retention policy. Snapshots also go stale against the branch and the base image, exactly like prebuilds do.

Optimize the Right Stage

Measure the breakdown before choosing a technique. If most of your cold start is a monorepo clone, a memory snapshot of an already-cloned workspace helps enormously and a faster image pull does almost nothing. See performance optimization.