The cost question is settled. At $0.0504 per vCPU-hour plus $0.0162 per GiB-hour on top of a $150-per-month Pro plan, E2B's meter crosses the price of a $70 Hetzner box at roughly 400 sandbox-hours a month — about one default sandbox running half the day, every day — as we worked through in E2B's $150/Month Sandbox Meter vs a $70 Hetzner Box. Below that line, rent the meter. Above it, the only interesting question left is the build: what does it actually take to run E2B-style ephemeral sandboxes — spin up, run untrusted agent-generated code, tear down — on machines you already own?
Here is the verdict up front, with the blueprint below: don't self-host E2B's stack and don't hand-roll Firecracker on day one — put a kata-fc RuntimeClass on the Cluster API fleet you already run. Self-hosting E2B's own infrastructure is real but means operating a second orchestrator (Nomad) next to your Kubernetes fleet, which is exactly the kind of toil a small platform team adopted Kubernetes to avoid. The K8s-native middle path gets you hardware-isolated, E2B-shaped sandboxes for days of platform work instead of months, keeps every migration door open, and defers the dedicated sandbox pool until cold-start latency — not cost — becomes the binding constraint.
The build spec: what "E2B-style" means
Before comparing builds, fix the spec. E2B's product is not "a VM with an API" — it is five primitives bundled behind one SDK, and a self-host has to replicate each one deliberately or decide it does not need it:
| Primitive | What to replicate | Budget to beat |
|---|---|---|
| Isolated execution | One Firecracker microVM per sandbox | $0.1656/hr for 2 vCPU / 4 GiB |
| Fast boot | ~150ms cold start from snapshot | Snapshot + warm-pool engineering |
| Pause/resume | Snapshot, stop billing, resume in ~1s | Snapshot store + scheduler support |
| Templates | Custom environments from Docker builds | A build/cache/GC pipeline |
| API + sessions | Sandbox.create() in Python/JS; 1h Hobby / 24h Pro sessions | An API shaped like E2B's (or the Agents SDK provider abstraction) |
Two footnotes scope the build. First, E2B sandboxes are CPU-only at every tier, so this post prices CPU execution only — GPU sandboxes are a different build on different nodes. Second, E2B is the right integration default on the way there: the April 2026 OpenAI Agents SDK made it one of seven native sandbox providers behind a bring-your-own abstraction, and our E2B vs Daytona vs Modal comparison picked it precisely for being Apache-2.0 with a documented self-host path, against Daytona's June 2026 move to a private codebase and Modal's closed cloud.
And "without the vendor lock-in" needs a definition, because three different lock-ins hide in one phrase. API lock-in: agent code written against E2B's SDK only runs on E2B unless an adapter exists. Template lock-in: custom environments in E2B's template format must be rebuilt in whatever the new platform consumes. Price lock-in: the per-second meter plus the $150 floor compounds with volume. A build removes the third completely and the first two only if you keep the E2B API shape as your interface — run something bespoke and you have traded vendor lock-in for self-lock-in, which bills in engineering hours instead of dollars.
Three paths, one physics
All three builds end at the same physics — KVM-backed microVMs on bare metal — but they differ in how much platform you operate and how much lock-in you retain:
| (a) Self-host E2B infra | (b) Kata on your K8s fleet | (c) Raw Firecracker pool | |
|---|---|---|---|
| What it is | e2b-dev/infra: E2B's own stack (Terraform + Nomad + Consul, Postgres, S3) | Kata Containers kata-fc RuntimeClass on existing CAPH nodes | Hand-rolled Firecracker + snapshot/warm-pool machinery |
| Boot time | ~150ms (same snapshot design) | Seconds per cold pod unless you add warm pools | ~150ms achievable — you build the snapshot pipeline |
| Isolation | Firecracker microVM | Firecracker/QEMU microVM per pod | Firecracker microVM |
| Ops burden | A second orchestrator estate to run | Days of work on infra you already operate | A second platform to operate, bespoke |
| Portability / lock-in | None added: E2B API/SDK and template format carry over; agents can't tell | Low: standard K8s API; keep the Agents SDK provider shape and migration is config | Highest: your API, your snapshot format — self-lock-in unless you mirror E2B's interface |
Path (a) is simultaneously open-source, API-compatible, and battle-tested — and it costs you a Nomad estate. The repo is Apache-2.0 and deploys with Terraform, but the architecture is Nomad servers plus Nomad client pools plus Consul plus managed Postgres and object storage. On a Cluster-API-managed Kubernetes fleet, adopting it means operating two orchestrators with two failure domains, two upgrade cadences, and two mental models — for a workload tier. That is a defensible trade at real scale, and the right framing is a compliance purchase for regulated teams whose data can't leave their perimeter, not a cost optimization. The 2026 sandbox guides summarize it honestly: self-hosting E2B is real but not turnkey.
Path (b) is the recommendation for almost everyone reading this, and the next section is its blueprint. Kata Containers is a CNCF project that runs each pod inside its own lightweight VM; the kata-fc handler backs it with Firecracker. You inherit Kubernetes scheduling, CNI networking, logging, and Prometheus metrics for free — the four subsystems path (c) makes you build. The price is cold-start latency: expect seconds per fresh pod (VM boot plus image pull), not 150ms. Close that gap later with pre-pulled images and a warm pool, not on day one.
Path (c) is what you graduate to when path (b)'s seconds become the product constraint. Firecracker's snapshot/restore primitives are upstream and documented, so pause/resume and snapshot-boot are genuinely buildable — E2B's 150ms is engineering, not magic. But "buildable" is doing heavy lifting: the snapshot store, the template build pipeline, per-microVM TAP networking wired into your CNI, the scheduler that bin-packs microVMs onto hosts, and the per-sandbox metering are each a subsystem. Take this path when sandbox latency or cost dominates your COGS with numbers to prove it, not because the architecture diagram looks clean.
The Kata path in concrete
This is the core deliverable: the actual sequence from "CAPH fleet with no sandbox tier" to "agent code running in per-pod microVMs." Five steps, no new orchestrator.
1. Confirm KVM on the node image. Kata and Firecracker both need /dev/kvm. Hetzner dedicated servers expose it; a plain VPS without nested virtualization does not. This single constraint is why "owned hardware" in this post means bare metal you control the kernel on. Verify it on your node image before anything else — everything below is moot without it.
2. Install Kata on sandbox-capable nodes. The upstream kata-deploy DaemonSet installs the Kata runtime and shims onto nodes and labels them; alternatively, bake Kata into your node image build so every machine CAPH provisions arrives sandbox-ready. Either way, taint or label the sandbox-capable nodes (katacontainers.io/kata-runtime: "true") so ordinary workloads never land on KVM-pinned capacity by accident.
3. Register the RuntimeClass. One cluster-scoped object opts the fleet into Firecracker-backed pods, with scheduling pinned to the labeled nodes and per-pod overhead declared so the scheduler bin-packs honestly:
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: kata-fc
handler: kata-fc
overhead:
podFixed:
memory: "130Mi"
cpu: "250m"
scheduling:
nodeSelector:
katacontainers.io/kata-runtime: "true"4. Run sandboxes as ordinary pods. From here a sandbox is a pod with one extra field. Your existing container images are your templates — no Docker-to-snapshot pipeline to build, which is half of this path's advantage over raw Firecracker:
apiVersion: v1
kind: Pod
metadata:
name: agent-sandbox
labels:
sandbox-id: task-1234
spec:
runtimeClassName: kata-fc
containers:
- name: runner
image: registry.example.com/agent-runner:latest
resources:
requests: { cpu: "2", memory: "4Gi" }
limits: { cpu: "2", memory: "4Gi" }5. Wire the agent-facing API around it. The pod spec above is the execution primitive, not the product. The remaining work is a thin service that maps create → run → snapshot → destroy onto the Kubernetes API (plus the Agents SDK provider shape if you want E2B-compatible agents to move over unchanged), with per-sandbox network policy, resource quotas, and metering from day one. That service is measured in weeks; the two orchestrators it avoids are measured in headcount.
Set expectations honestly at each step. Cold pod start runs in seconds (guest boot plus image pull), not 150ms — pre-pull runner images onto sandbox nodes and keep a small warm pool before promising otherwise. The ~130 MiB / 250 mCPU overhead per pod is the Kata shim and guest kernel; size node headroom with it included. And keep the runner image small: every megabyte of image is cold-start latency on nodes that haven't pulled it yet.
The six gotchas the happy path skips
Every "just run Firecracker" sketch omits the same constraints. Budget for them during the build, not during the outage:
- KVM or nothing. Covered in step 1, repeated because it is the most common dead end: nested virtualization (GCP supports it; most cheap VPSes don't) or bare metal. No
/dev/kvm, no microVMs, no appeal. - The template pipeline is a product. E2B's Docker-to-snapshot template builds look like a feature and operate like a CI system: build, cache, version, garbage-collect. Path (b) sidesteps this elegantly (templates are just container images), which is half its advantage — but "just images" still needs a registry retention policy and a base-image CVE process.
- Per-sandbox networking is a security control. Inside Kubernetes, CNI plus NetworkPolicy handles it: default-deny egress per sandbox namespace, explicit allowlists for package registries and model APIs, no route to the cloud metadata service. Below Kubernetes, every microVM needs a TAP device, an IP, and a policy — the plumbing path (c) hand-builds. Either way, egress policy for untrusted agent-generated code is not a nice-to-have.
- Pause/resume parity decides your cost story. E2B stops billing while a sandbox is paused and resumes in about a second. If your build cannot overcommit paused sandboxes to near-zero CPU, the "owned wins past ~400 sandbox-hours" math quietly assumes utilization your scheduler cannot deliver. Firecracker snapshots make parity achievable; nothing makes it free — this is the subsystem most teams underestimate.
- Oversubscription policy is a noisy-neighbor policy. A 16-thread box hosts eight 2-vCPU sandboxes with no oversubscription, or dozens the way E2B packs its own hosts. The moment you oversubscribe, one tenant's compile storm is another tenant's stalled agent turn — and agent turns are latency-sensitive in a way batch jobs are not. Set the policy (dedicated threads vs. shared pool) before tenants discover it empirically.
- Per-sandbox observability is per-tenant billing evidence. CPU-seconds, memory high-water, network egress, and kill reason per sandbox — meter it from day one even when you charge nothing for it, because the month you introduce usage-based pricing without historical data is the month every invoice gets disputed.
Where it lands on the roadmap
Sequenced by trigger, not by ambition — each phase has a number attached so "later" means something:
- Phase 0 — integrate the metered API (today, while Hobby suffices). Ship agent execution against E2B (or the Agents SDK provider abstraction) and pay per second. Trigger to leave: you outgrow Hobby's 20 concurrent sandboxes or 1-hour sessions, sustained volume approaches the ~400 sandbox-hour crossover, or a tenant requires execution inside your trust boundary. Cost of the phase: usage only.
- Phase 1 — Kata tier on the existing fleet (past the crossover, or data-sovereignty demand). The five steps above: KVM check, Kata install, RuntimeClass, pod-shaped sandboxes, thin API. Keep the provider-shaped interface so agents never notice the move. Trigger to leave: p99 cold start (seconds) shows up in agent-task latency as the binding constraint, with traces to prove it.
- Phase 2 — dedicated sandbox pool (thousands of sandbox-hours a month, or a sub-second boot SLA). Warm snapshot pools, a template pipeline, per-tenant network policy, and real metering — path (c), or path (a) if you would rather operate Nomad than bespoke code. Trigger to enter: sandbox COGS or latency dominates a P&L line, not a whiteboard.
Note what this roadmap never does: it never pays the Pro floor and operates hardware for the same workload, never builds path (c) before path (b) has production traffic, and never invents a bespoke sandbox API when the E2B/Agents-SDK shape keeps every future migration a config change. The lock-in this post removes is the price lock-in; the API compatibility is what keeps it removed.
Rent the primitive to learn; own the RuntimeClass to scale
Per-second billing plus sub-second starts made the sandbox disposable, and disposable sandboxes made agent architectures possible. That was E2B's real contribution — bigger than any rate on the price list. But disposability is a property of Firecracker, not of E2B's invoice: once your sandbox-hours are steady enough to forecast past the ~400-hour crossover, the same disposability runs on machines you own, and the cheapest way to collect the win is not a second orchestrator but a RuntimeClass on the fleet you already operate. Build the Kata tier when the meter tells you to, keep the provider-shaped API so the move is invisible to your agents, and save raw Firecracker for the day cold-start seconds show up in your traces.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.



