# Performance Comparisons Between Secure Container Runtimes Supported by OpenSandbox

> Compare secure container runtimes like gVisor and Kata Containers with Firecracker and QEMU in OpenSandbox. Discover optimal performance for AI workloads and memory efficiency.

- Repository: [Alibaba/OpenSandbox](https://github.com/alibaba/OpenSandbox)
- Tags: performance
- Published: 2026-03-08

---

**gVisor delivers the best balance for AI workloads with 10–50 ms cold-start overhead and ~50 MiB memory per sandbox, while Kata Containers with Firecracker minimizes memory to ~5 MiB with 125 ms startup, and Kata with QEMU provides maximum isolation at the cost of ~500 ms cold-start latency.**

OpenSandbox extends beyond the default `runc` implementation to support multiple **secure container runtimes** that provide varying levels of isolation for untrusted code execution. Understanding the **performance comparisons between different secure container runtimes** is critical for operators balancing security guarantees against startup latency and memory density in production AI-code environments. The benchmarks documented in **OSEP‑0004** and the user guide at [`docs/secure-container.md`](https://github.com/alibaba/OpenSandbox/blob/main/docs/secure-container.md) provide the empirical basis for these deployment decisions.

## Secure Container Runtime Performance Characteristics

OpenSandbox supports five distinct runtime configurations, each trading isolation depth against resource overhead. The following table summarizes the cold-start latency and memory footprint per sandbox as documented in OSEP‑0004 lines 16‑22 and [`docs/secure-container.md`](https://github.com/alibaba/OpenSandbox/blob/main/docs/secure-container.md) lines 23‑29:

| Runtime | Isolation Mechanism | Startup Overhead (cold) | Memory Overhead per Sandbox | Typical Use Case |
|---------|--------------------|------------------------|-----------------------------|-----------------|
| **runc** (default) | Process-level cgroups | ~0 ms | Minimal (≈ 5 MiB) | Trusted workloads, local development |
| **gVisor** | User-space kernel intercepting syscalls | ~10–50 ms | ≈ 50 MiB | General AI-code workloads requiring low overhead |
| **Kata (QEMU)** | Full virtual machine via QEMU hypervisor | ~500 ms | 20–50 MiB | Maximum compatibility and isolation for untrusted code |
| **Kata (Firecracker)** | Micro-VM using Firecracker hypervisor | ~125 ms | ≈ 5 MiB | High-density multi-tenant workloads |
| **Kata (CLH)** | Cloud Hypervisor-based VM | ~200 ms | 10–20 MiB | Balanced performance and isolation |

## Architectural Implementation

OpenSandbox selects the runtime **once at server start-up** via the `[secure_runtime]` section of `~/.sandbox.toml`. The server validates runtime availability against the Docker daemon or Kubernetes `RuntimeClass` objects, then transparently injects the appropriate flag into every sandbox creation request.

### Runtime Resolution Logic

The central mapping logic resides in [`server/src/services/runtime_resolver.py`](https://github.com/alibaba/OpenSandbox/blob/main/server/src/services/runtime_resolver.py). The `SecureRuntimeResolver` class provides two primary methods:

- `get_docker_runtime()` (lines 39‑53): Returns the OCI runtime name (e.g., `runsc` for gVisor, `kata-runtime` for Kata) that `DockerSandboxService` injects into the Docker `HostConfig` runtime field.
- `get_k8s_runtime_class()`: Returns the `RuntimeClass` name used by `BatchSandboxProvider` and `AgentSandboxProvider` to populate the pod spec’s `runtimeClassName` field.

Because the runtime is a **server-level configuration**, client code using the SDK or REST API requires **no changes** when switching from `runc` to a secure runtime.

### Server-Level Configuration

Operators define the active runtime in `~/.sandbox.toml`:

```toml
[secure_runtime]
type = "gvisor"  # Options: "", "gvisor", "kata", "firecracker"

docker_runtime = "runsc"  # For Docker mode

k8s_runtime_class = "kata-fc"  # For Kubernetes mode

```

The `type` field determines which isolation mechanism the `SecureRuntimeResolver` maps to the underlying container engine.

## Cold Start vs Warm Start Optimization

OpenSandbox mitigates the high cold-start cost of VM-based runtimes through **pre-warmed pools**. As documented in OSEP‑0004 lines 24‑30, warm-start latencies drop dramatically when sandboxes are recycled:

- **Kata (QEMU)**: Cold start ~1000 ms → Warm start ~200 ms
- **Kata (Firecracker)**: Cold start ~125 ms → Warm start ~50 ms (estimated from pool amortization)

This optimization makes Kata runtimes viable for latency-sensitive workloads when paired with OpenSandbox’s pool management.

## Practical Configuration Examples

The following CLI snippets demonstrate how to configure each runtime. The API payload remains identical across all examples; only the server-side `~/.sandbox.toml` configuration changes.

### gVisor (Docker Mode)

Configure `~/.sandbox.toml`:

```toml
[secure_runtime]
type = "gvisor"
docker_runtime = "runsc"

```

Create a sandbox:

```bash
curl -X POST http://localhost:8080/v1/sandboxes \
  -H "Content-Type: application/json" \
  -d '{
        "image": {"uri":"python:3.11"},
        "entrypoint":["python","-c","print(\"gVisor sandbox\")"]
      }'

```

Verify the runtime:

```bash
docker inspect $(docker ps -q --filter "ancestor=python:3.11") | grep Runtime

# Expected: "Runtime": "runsc"

```

### Kata with QEMU (Docker Mode)

Configure `~/.sandbox.toml`:

```toml
[secure_runtime]
type = "kata"
docker_runtime = "kata-runtime"

```

Create a sandbox:

```bash
curl -X POST http://localhost:8080/v1/sandboxes \
  -H "Content-Type: application/json" \
  -d '{
        "image": {"uri":"ubuntu:latest"},
        "entrypoint":["/bin/bash","-c","uname -a"]
      }'

```

Verify the guest kernel:

```bash
docker exec $(docker ps -q --filter "ancestor=ubuntu:latest") uname -a

# Output shows Kata guest kernel (e.g., 5.10.x-kata)

```

### Kata with Firecracker (Kubernetes Mode)

Configure `~/.sandbox.toml`:

```toml
[secure_runtime]
type = "firecracker"
k8s_runtime_class = "kata-fc"

```

After creating a sandbox via the API, verify the RuntimeClass:

```bash
kubectl get pod <sandbox-pod> -o jsonpath='{.spec.runtimeClassName}'

# Expected output: kata-fc

```

### Default runc (No Secure Runtime)

Configure `~/.sandbox.toml`:

```toml
[secure_runtime]
type = ""

```

Create a sandbox:

```bash
curl -X POST http://localhost:8080/v1/sandboxes \
  -H "Content-Type: application/json" \
  -d '{
        "image": {"uri":"python:3.11"},
        "entrypoint":["python","-c","print(\"runc sandbox\")"]
      }'

```

Verify:

```bash
docker inspect $(docker ps -q --filter "ancestor=python:3.11") | grep Runtime

# Expected: "Runtime": "runc"

```

## Selecting the Right Runtime for Your Workload

Choose your runtime based on the trust level of the executing code and your performance constraints:

- **gVisor**: Select this for most production AI-code execution scenarios. It provides syscall-level isolation with only 10–50 ms startup penalty and moderate memory overhead (~50 MiB), making it suitable for general untrusted workloads where low latency is desired.

- **Kata (QEMU)**: Deploy this when absolute isolation is required for untrusted network code or kernel exploits. The full VM model ensures maximum compatibility but imposes ~500 ms cold-start latency and 20–50 MiB memory overhead.

- **Kata (Firecracker)**: Use this for high-density multi-tenant environments where memory efficiency is paramount. The micro-VM architecture achieves ~125 ms startup with only ~5 MiB overhead, comparable to `runc` but with hardware virtualization isolation.

- **Kata (CLH)**: Choose Cloud Hypervisor when you need a middle ground between Firecracker’s speed and QEMU’s compatibility, offering ~200 ms startup with 10–20 MiB overhead.

## Summary

- OpenSandbox supports five secure container runtimes—`runc`, **gVisor**, and three **Kata** variants (QEMU, Firecracker, CLH)—each offering distinct trade-offs between isolation strength and resource overhead.
- **gVisor** provides the lowest overhead among secure options (~10–50 ms startup, ~50 MiB memory) by intercepting syscalls in user space rather than using hardware virtualization.
- **Kata with Firecracker** achieves the highest density (~5 MiB memory, ~125 ms startup) through micro-VM technology, making it ideal for multi-tenant scenarios.
- Runtime selection is configured server-side in `~/.sandbox.toml` and resolved transparently by `SecureRuntimeResolver` in [`server/src/services/runtime_resolver.py`](https://github.com/alibaba/OpenSandbox/blob/main/server/src/services/runtime_resolver.py), requiring no client code changes.
- Warm-start pools mitigate cold-start penalties for VM-based runtimes, reducing Kata (QEMU) latency from ~1000 ms to ~200 ms.

## Frequently Asked Questions

### What is the fastest secure container runtime supported by OpenSandbox?

**gVisor** is the fastest secure runtime, adding only 10–50 ms of cold-start overhead compared to the ~0 ms of standard `runc`. While `runc` itself is faster, it provides only process-level isolation via cgroups. For workloads requiring actual syscall interception or kernel isolation, gVisor outperforms Kata variants by avoiding the full VM boot process.

### How do I verify which runtime is actually executing my sandbox?

For **Docker mode**, inspect the container’s runtime field using `docker inspect <container-id> | grep Runtime`. When using gVisor, this returns `"runsc"`; for Kata, it returns `"kata-runtime"`; for default operation, it shows `"runc"`. In **Kubernetes mode**, check the pod’s `runtimeClassName` field with `kubectl get pod <name> -o jsonpath='{.spec.runtimeClassName}'`, which returns values like `kata-fc` for Firecracker.

### Can I switch between secure runtimes without modifying my client application code?

Yes. OpenSandbox treats runtime selection as a **server-level configuration** defined in `~/.sandbox.toml` under the `[secure_runtime]` section. The `SecureRuntimeResolver` class in [`server/src/services/runtime_resolver.py`](https://github.com/alibaba/OpenSandbox/blob/main/server/src/services/runtime_resolver.py) transparently injects the appropriate Docker `--runtime` flag or Kubernetes `runtimeClassName` during sandbox creation. Client SDKs and REST API calls remain identical regardless of whether the backend uses `runc`, gVisor, or Kata.

### Why does Kata with QEMU consume significantly more memory than Kata with Firecracker?

**Kata with QEMU** provisions a full virtual machine including a complete QEMU system emulator and a heavyweight guest kernel, resulting in 20–50 MiB of memory overhead per sandbox. In contrast, **Kata with Firecracker** utilizes a micro-VM architecture that strips unnecessary devices and firmware, reducing the memory footprint to approximately **5 MiB**—comparable to standard container overhead while maintaining hardware-level isolation. This makes Firecracker ideal for high-density multi-tenant deployments where QEMU’s resource consumption would be prohibitive.