Sign Up

GPU Sandboxes

GPU sandboxes, their capabilities, use cases, and architecture.

GPU sandboxes are GPU virtual machines (VMs). Each sandbox has one or more dedicated NVIDIA or AMD GPUs attached to it on shared physical hardware. The hardware enforces the boundary and isolation between sandboxes. Code inside it can train and fine-tune models, serve inference, and run any program built on CUDA, NVIDIA's platform for general-purpose computing on GPUs. Each GPU sandbox has dedicated GPUs, is always ephemeral, and can save its state as a checkpoint that includes GPU memory.

TermDescription
GPUA processor built for parallel computation, used for machine learning, simulation, and graphics.
VRAMThe memory on a GPU. Models, weights, and intermediate results live in VRAM while the GPU works on them.
CUDANVIDIA's platform and libraries for running general-purpose programs on NVIDIA GPUs. PyTorch, vLLM, and most ML frameworks use it.
NVIDIA driverThe software that controls NVIDIA GPUs. Programs reach a GPU through requests to this driver.
CheckpointA saved copy of a running GPU sandbox's processes, memory, and GPU memory that a new GPU sandbox can resume from.

Use cases

Use GPU sandboxes for GPU code you cannot trust or must keep isolated.

  • Inference: a model in VRAM, served for example with vLLM or SGLang, answers requests through a preview URL or from code in the sandbox.
  • Training and fine-tuning: a job trains on whole GPUs that no other sandbox shares, with the dataset and outputs in the sandbox. The shared memory directory is sized at 40 GiB per GPU for PyTorch data loaders and NCCL.
  • AI-generated GPU code: an agent writes CUDA, PyTorch, or other GPU code, runs it on a real GPU, and reads the result, without access to your infrastructure.
  • Evaluation and benchmarks: each model, checkpoint, or test case runs on its own GPU in a clean environment, so results do not depend on another run.
  • Reinforcement learning (RL): policies that need a GPU for rollouts or updates run in isolated environments that are created and deleted per run.
  • Pausing expensive work: a long job is checkpointed to release its GPU and resumed later, or on another GPU of the same model, from the point it was saved.
  • Fast model starts: a checkpoint taken after a model loads holds the model in GPU memory. A new GPU sandbox restored from it serves the model without loading it again.
  • Image generation and graphics: RTX GPUs run image generation, rendering, graphics workloads, and CUDA development at a lower cost than data center GPUs.

Create a GPU sandbox

Create a GPU sandbox from the dashboard or programmatically.

  1. Go to Daytona Sandboxes ↗
  2. Click Create
  3. Select GPU sandbox
  4. Click Create
curl 'https://api.daytona.com/sandboxes/gpu' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{"image": "pytorch", "gpu_host": 1}'

The following example sets the remaining fields:

# Source: image is a registered image name or img_ id
# GPUs: gpu_host is a count, or gpu is an array of host PCI addresses instead
# Resources: cpu in cores, mem_mib and scratch_mib in MiB
# Networking: ports entries are {vm_port, proto?}
curl 'https://api.daytona.com/sandboxes/gpu' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "image": "pytorch",
  "gpu_host": 1,
  "name": "my-gpu-sandbox",
  "labels": { "team": "ml", "run": "42" },
  "user": "root",
  "cpu": 4,
  "mem_mib": 16384,
  "scratch_mib": 102400,
  "ports": [{ "vm_port": 8000 }],
  "env": { "HF_HOME": "/root/.cache/huggingface" },
  "secrets": ["HF_TOKEN"],
  "region": "us",
  "lifecycle": {
    "idle_timeout_secs": 3600,
    "on_idle_timeout": "delete",
    "timeout_secs": 86400,
    "on_timeout": "delete"
  },
  "idempotency_key": "run-42-create"
}'
FieldTypeDescription
imagestringSets the registered image that the sandbox starts from, by name or img_ ID. This field is required.
gpu_hostintegerSets the number of GPUs to attach. The runner selects the physical cards. Set exactly one of gpu_host and gpu.
gpuarrayPasses GPUs through to the sandbox by host PCI address. Set exactly one of gpu and gpu_host.
namestringSets the display name. If omitted, a name is generated.
labelsobjectAttaches key-value metadata to the sandbox.
userstringSets the default OS user inside the sandbox. The default is root.
cpunumberSets the guaranteed CPU cores as a float. The value is raised to at least one core per 4 GiB of guaranteed memory. The default is 0.125.
vcpusintegerSets an integer CPU request. It applies only if cpu is absent. The default is 2.
mem_mibintegerSets the guaranteed memory in MiB. The default is 1024.
scratch_mibintegerSets the guaranteed writable disk in MiB. The default is 512.
portsarrayForwards inbound ports to the sandbox.
envobjectSets environment variables inside the sandbox.
secretsarrayAttaches project secrets by name. The sandbox sees each secret as an opaque placeholder.
regionstringSets the region or global region slug. The default is the project default.
lifecycleobjectSets the lifecycle policy with timeout_secs and on_timeout, and idle_timeout_secs and on_idle_timeout. The only action is delete. By default, there is no idle timeout, and the wall-clock timeout uses the organization or platform default, if one is enabled.
idempotency_keystringMakes a retried create return the same sandbox. You can also send it as the Idempotency-Key header.

The response has the following fields:

FieldDescription
statusThe status is often pending, because the server holds the request for at most 3 seconds by default. Poll GET /sandboxes/{sandboxId}?wait=running until the sandbox is running.

GPUs

Daytona provides the following GPU models. Availability depends on the region.

GPUDescription
NVIDIA H100Data center GPU for training and serving large models. The common choice for fine-tuning and for inference with vLLM or SGLang.
NVIDIA H200Same compute as the H100 with more and faster memory. Holds larger models and longer context windows in VRAM, which raises inference throughput for memory-bound workloads.
NVIDIA B200Data center GPU for training and serving large models. More compute and VRAM than the H200, and it adds FP4 precision for inference.
NVIDIA B300Data center GPU for the largest models. Its VRAM fits models that need several H100s on one GPU, and it adds FP4 precision for inference.
NVIDIA RTX PRO 6000Workstation and server GPU. Serves and fine-tunes mid-size models at a lower price than data center GPUs, and runs rendering and graphics workloads.
NVIDIA RTX 4090Consumer GPU. Runs small models, quantized inference, image generation, and CUDA development at the lowest cost.
NVIDIA RTX 5090Consumer GPU. Same uses as the RTX 4090 with more VRAM, more memory bandwidth, and FP4 support.
AMD Instinct MI355XAMD data center GPU for training and inference of large models. Programs use ROCm, AMD's platform for GPU computing, instead of CUDA. PyTorch and vLLM ship ROCm builds.

GPU allocation

A create request asks for a number of GPUs. Daytona places the sandbox on a host with that many free GPUs of the region's kind and assigns whole physical GPUs to it. A GPU is never shared: each belongs to exactly one sandbox until that sandbox is deleted.

GPUs are reserved exactly. A host with three GPUs runs at most three single-GPU sandboxes, and a request that no host in the region can satisfy fails instead of sharing a GPU. Processor and memory on GPU hosts follow the same guarantees and resource limits as Linux sandboxes; only GPUs are never shared or oversubscribed.

Lifecycle

Every GPU sandbox moves through a lifecycle. A GPU sandbox can have several different states. Each state reflects the status of your sandbox. A GPU sandbox transitions between states in response to user actions, or automatically when one of its timeouts elapses.

FeatureEphemeral
Stop and start✗
Pause and resume✗
Fork✗
Delete✓
Filesystem persistence✗
Memory persistence✗
Memory snapshot✓ checkpoint
Filesystem snapshot✗
Spot (Preemption)✗
Network policy✗
Desktop✗

Every GPU sandbox supports wait for state, delete, timeouts, and lifecycle policy updates. GPU sandboxes are always ephemeral: the writable filesystem exists until the sandbox is deleted, and deleting the sandbox releases its GPUs. GPU sandboxes do not support stop, start, pause, resume, or fork. To keep the state of a GPU sandbox, take a checkpoint. Restoring a checkpoint creates a new GPU sandbox that moves through the same states as a create.

Sandbox states
StateDescription
queuedThe create request is recorded and waits to be published for placement.
pendingThe create request is accepted and the sandbox is queued for placement on a host with free GPUs.
assignedThe sandbox is placed on a host and its GPUs are reserved.
bootingThe root filesystem is assembled, the GPUs are attached, and the sandbox is starting.
runningThe sandbox is running and ready to accept requests.
deletingThe sandbox is being deleted.
deletedThe sandbox and its writable filesystem are removed, and its GPUs are released.
failedThe sandbox could not start or hit an unrecoverable error.
lostThe host running the sandbox was lost. A checkpoint taken earlier can still be restored.
State transitions
Initial stateTarget stateTrigger
queuedpendingThe create or restore request is published for placement.
pendingassignedThe sandbox is placed on a host with enough free GPUs.
assignedbootingThe host assembles the root filesystem and attaches the GPUs.
bootingrunningThe sandbox daemon answers, the sandbox's secrets are delivered, and the sandbox accepts requests.
any statedeletingA delete is requested, or a timeout elapses.
deletingdeletedThe sandbox is removed and its GPUs are released.
any active statefailedThe sandbox fails to start or hits an unrecoverable error.
runninglostThe host running the sandbox is lost.

Wait for state

Wait until a GPU sandbox reaches a target state. The wait stops early when the sandbox reaches a state from which the target is no longer reachable, such as failed or deleted. The SDKs use their own state names, so the SDK started state corresponds to the running state in the CLI and API. A GPU sandbox never enters the stopping, pausing, or paused states.

# Block until the sandbox is started; returns the sandbox
sandbox.wait(until="started", timeout=60)

# Block until the sandbox is destroyed
sandbox.wait_for_state(["destroyed"], timeout=60)
ParameterTypeDescription
untilstrSets the one state that wait() waits for. wait_for_state() takes a list and returns on any of its states. The default is "started".
timeoutfloatSets the wait limit in seconds. None or 0 waits without a limit. When the timeout elapses, both methods raise RequestTimeoutError. The default is 60 for wait() and None for wait_for_state().

Delete

Delete a GPU sandbox to tear down its virtual machine. Deletion works in any state, and the call returns once teardown starts. The sandbox moves from deleting to deleted when the teardown finishes. Daytona releases the sandbox's GPUs and discards its writable filesystem, memory, and GPU memory. Checkpoints taken from the sandbox remain. To keep the state of a running sandbox, create a checkpoint before you delete it.

from daytona import Daytona

daytona = Daytona()
sandbox = daytona.v2.get("{sandboxId}")

sandbox.delete()

Timeouts

Daytona deletes a GPU sandbox automatically when one of its two timers elapses. Each timer pairs an interval in seconds with the action it fires. Set both timers at create in the lifecycle object, and change them later through update lifecycle policy.

TimerPurposeFires afterDefault
TimeoutCap how long a sandbox runsThe sandbox has been running for the interval, active or notProject or platform default
Idle timeoutDelete a sandbox that is not in useThe sandbox has had no activity for the intervalProject default, or off

Delete is the only valid action on both timers:

ActionGPU sandbox
Stop✗
Pause✗
Delete✓

Auto-delete is not a separate setting. It is the idle timeout with the delete action. The stop and pause actions and wake on request are not available for GPU sandboxes. Because every timer on a GPU sandbox deletes it, a lifecycle policy update and an idle timer reset require the delete:sandboxes permission in addition to write:sandboxes.

Timeout

The timeout is a wall-clock budget. It starts when the sandbox is created. Activity does not extend it. The timeout fires in any state. Once set, the timeout cannot be cleared.

When the timeout is omitted at create, Daytona applies the ephemeral block of the project's lifecycle defaults. Without a project default, Daytona applies the platform default timeout of 300 seconds, if the platform default is enabled. An explicit timeout must not exceed the organization maximum, 86,400 seconds (24 hours) unless the organization sets a different maximum.

When the action is omitted, it defaults to delete.

# Delete the sandbox 2 hours after it entered running
curl 'https://api.daytona.com/sandboxes/gpu' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "image": "pytorch",
  "gpu_host": 1,
  "lifecycle": { "timeout_secs": 7200, "on_timeout": "delete" }
}'

Idle timeout

The idle timeout fires after the sandbox has had no activity for the interval. Activity is any request through the toolbox API, preview URLs, and SSH, and any lifecycle operation on the sandbox. The idle timeout is off by default unless the project sets one, has a minimum of 60 seconds, and requires an action. The action fires within about 2 minutes after the interval elapses.

Auto-delete

Delete a GPU sandbox after a period of inactivity. Deleting the sandbox releases its GPUs.

curl 'https://api.daytona.com/sandboxes/gpu' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{
  "image": "pytorch",
  "gpu_host": 1,
  "lifecycle": { "idle_timeout_secs": 3600, "on_idle_timeout": "delete" }
}'
Reset the idle timer

Reset the idle timer of a GPU sandbox to keep it alive while it does work that Daytona does not count as activity. The reset counts as activity, so the idle countdown restarts from now. The timeout is not affected.

The reset succeeds in any state, whether or not an idle timeout is set. It never moves the timer backwards: when newer activity arrives at the same time, the newer activity wins.

from daytona import Daytona

daytona = Daytona()
sandbox = daytona.v2.get("{sandboxId}")

lifecycle = sandbox.reset_idle_timer()
print(lifecycle.idle_timeout_at)

Update lifecycle policy

Update the timeouts of an existing GPU sandbox. Omitted fields keep their current values. Delete is the only valid action, as listed in timeouts.

from daytona import Daytona
from daytona.v2 import DISABLED

daytona = Daytona()
sandbox = daytona.v2.get("{sandboxId}")

# Delete the sandbox after 30 minutes without activity; omitted fields keep their current value
lifecycle = sandbox.set_lifecycle(idle_timeout_secs=1800, on_idle_timeout="delete")
print(lifecycle.idle_timeout_secs, lifecycle.on_idle_timeout)

# Re-anchor the timeout to 1 hour from now
lifecycle = sandbox.set_lifecycle(timeout_secs=3600)
print(lifecycle.timeout_at)

# Clear the idle timeout
lifecycle = sandbox.set_lifecycle(idle_timeout_secs=DISABLED)

Checkpoint

A checkpoint saves the processes, memory, and GPU memory of a running GPU sandbox under a name. A new GPU sandbox restored from the checkpoint continues from the point the checkpoint was taken, instead of booting and loading its models again. GPU sandboxes are always ephemeral, so a checkpoint is the only way to keep the state of a GPU sandbox.

CapturedContents
Processes and memoryEach process's memory, open files, and execution point.
GPU memoryVRAM, including loaded models, via NVIDIA's cuda-checkpoint.
Filesystem lineageThe source image, so the restore has the same software.

The sandbox is frozen while the checkpoint is written. Freezing and restoring take longer the more GPU memory the sandbox uses, because GPU memory is copied out and back in. The capture runs in the background: the checkpoint starts as pending and becomes ready when its capture job finishes.

Daytona places a restore only on a host where it can succeed:

  • The host has the same GPU model and the same NVIDIA driver branch as the checkpoint.
  • The host has enough free VRAM for the checkpoint's GPU memory, checked before the restore.

The restored sandbox can run on a different physical GPU from the original. It gets a new address, and it keeps the operating system user of the original sandbox.

# Capture the processes, memory, and GPU memory of the running sandbox
curl 'https://api.daytona.com/sandboxes/{sandboxId}/snapshots' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{"name": "my-checkpoint"}'

# Block until the checkpoint is ready
curl 'https://api.daytona.com/snapshots/{snapshotId}?wait=ready' \
  --header 'Authorization: Bearer YOUR_API_KEY'

# Continue from the checkpoint in a new GPU sandbox
curl 'https://api.daytona.com/sandboxes/gpu/from-snapshot' \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --data '{"snapshot": "my-checkpoint"}'

The capture request returns the pending checkpoint and the job that captures it:

{
  "job_id": "5f0c2a8e-3b1d-4c7e-9a2f-6d8e1b4c0a37",
  "kind": "checkpoint",
  "name": "my-checkpoint",
  "snapshot_id": "snap_7fJk2mQpXv9dLc3RtY",
  "status": "pending",
  "vm_id": "{sandboxId}"
}

POST /sandboxes/{sandboxId}/snapshots accepts the following field:

FieldTypeDescription
namestringSets the checkpoint name. The name has 1 to 128 characters from A-Z, a-z, 0-9, ., _, and -. It must not start with . or prj-, and it must be unique in the project. This field is required.

POST /sandboxes/gpu/from-snapshot accepts the following fields:

FieldTypeDescription
snapshotstringSets the checkpoint to restore, by name or snap_ ID. This field is required.
namestringSets the display name. If omitted, a name is generated.
labelsobjectAttaches key-value metadata to the sandbox.
lifecycleobjectSets the lifecycle policy with timeout_secs and on_timeout, and idle_timeout_secs and on_idle_timeout. The only action is delete.
portsarrayForwards inbound ports to the sandbox.
regionstringSets the region or global region slug. The default is the project default.
idempotency_keystringMakes a retried create return the same sandbox. You can also send it as the Idempotency-Key header.
create_ttlintegerSets how many seconds the sandbox has to reach running before it is deleted. The default is 3600, and the maximum is 86400.
waitintegerSets how long the server holds the request for the sandbox to start. By default, the server holds it for at most 3 seconds.