Skip to main content

Where Lovable, bolt.new, and v0 Run Your Generated Code: Firecracker vs gVisor vs Docker, Priced Against a Hetzner Box

10 min readDora NodaDora Noda
Share
On this page

Every prompt you type into Lovable, bolt.new, or v0 ends the same way: untrusted code, written by a model, needs to run somewhere before anyone trusts it. That "somewhere" is the most consequential infrastructure decision these products made — and the three market leaders made three completely different choices.

bolt.new runs your generated app inside your own browser tab. v0 runs it in a Firecracker microVM on Vercel's servers. Lovable runs it in cloud-hosted preview containers, one per project. Browser sandbox, hardware-isolated microVM, shared-kernel container: three rungs of the same ladder, with a roughly 10x spread in boot latency and a real spread in what "isolated" actually guarantees.

This post surveys that ladder rung by rung — Firecracker microVMs, gVisor, and Docker-plus-seccomp as the baseline — with boot-latency ranges, isolation strength, overhead numbers, and per-execution cost, priced against the same workload on a rented Hetzner box you own outright. The short version is in the two tables below; the rest of the post substantiates every row. If you run a self-hosted platform and need a preview path for agent-generated code, the last section maps each rung to the trust level it actually earns.

ProductWhere generated code runsIsolation rung
bolt.new (StackBlitz)StackBlitz WebContainers — Node.js compiled to WebAssembly, executed in the visitor's browser tabRung 0: browser sandbox, zero server compute
v0 (Vercel)Vercel Sandbox — Firecracker microVMs, ephemeral, billed on active CPU (reported at ~$0.128/vCPU-hr)Rung 1: hardware microVM boundary
LovableCloud-hosted preview containers, roughly one live environment per project (Lovable publishes no sandbox substrate; placement is by observable behavior — a per-project container running a dev server, not a per-execution microVM)Rung 2/3 class: container boundary
Open-source clones (bolt.diy, vibra-code mold)E2B cloud sandboxes — Firecracker microVMs at a reported ~$0.05/vCPU-hr, ~100–200 ms bootRung 1: hardware microVM boundary
Rung 1: Firecracker microVMRung 2: gVisorRung 3: Docker + seccomp/AppArmor
BoundaryDedicated guest kernel per sandbox (KVM)Syscall interception on the shared host kernelShared kernel, filter-only (seccomp profiles, AppArmor/SELinux)
Boot to execution~100–200 ms reported (E2B-class); sub-90 ms claimed by the fastest vendors~300–800 ms effective start; Sentry process ~50 MB~20 ms container start, ~1% CPU overhead
Steady-state overhead~5% CPU, ~5 MB memory per microVM~10–50% I/O overhead on syscall-heavy workloadsNear-native; the kernel is the kernel
Docker compatibilityNo — own microVM API, OCI images via templatesYes — runs as an OCI runtime (--runtime=runsc)Yes — it is the default
GPU storyWeak (Vercel Sandbox: none; E2B: via templates only)Strong (Modal's gVisor fleet serves T4-to-H100 workloads)Native device passthrough, no extra isolation for the device path
Trust level earnedUntrusted model output, multi-tenant by defaultUntrusted code with a compatibility requirement, or GPU workloadsCode a human already reviewed

Rung 1: Firecracker microVMs — a kernel per execution

Firecracker, originally built at AWS for Lambda and Fargate, boots a minimal guest kernel in a microVM with no BIOS, no emulated devices beyond virtio, and a memory footprint around 5 MB. E2B, the canonical agent-sandbox vendor in this mold, reports ~100–200 ms cold starts, per-second billing at roughly $0.05 per vCPU-hour, pause/resume that freezes filesystem plus memory plus processes, and a self-hostable enterprise tier. Daytona pushes the same primitive below a reported 90 ms with persistent workspaces and snapshots. Vercel Sandbox puts v0's generated code in the same class of boundary — ephemeral microVMs billed on active CPU at a reported $0.128 per vCPU-hour plus provisioned memory.

Why this rung owns the "untrusted generated code" slot: the tenant's code shares nothing with the host except the hypervisor. A container escape buys the attacker a guest kernel, not your fleet's kernel. That is the property you want when the code was written thirty seconds ago by a model optimizing for "looks right" rather than "is safe" — which is precisely what a deploy-from-chat preview path executes.

The costs are real but narrow. Per-execution billing means bursty preview traffic is cheap (a 30-minute agent run on one vCPU lands around $0.025–0.10 at these list prices), while sustained load gets expensive fast — a single vCPU busy around the clock is ~$36/month at E2B rates, before memory. GPU support is the thin spot: Vercel Sandbox offers none inside the sandbox, and E2B's GPU path runs through templates rather than first-class scheduling. And raw Firecracker is an API, not a platform — snapshot/restore, networking, and orchestration are yours to build, which is exactly the gap E2B, Daytona, and Vercel Sandbox charge for closing.

Rung 2: gVisor — syscall filtering when you need Docker compatibility or GPUs

gVisor takes the opposite approach from Firecracker: instead of a guest kernel, it interposes a user-space kernel (the Sentry process) between the container and the host, intercepting and filtering every system call. It runs as a drop-in OCI runtime, so any Docker image works unmodified — the property that made Modal, the canonical gVisor-at-scale vendor, the default choice for GPU-heavy agent workloads that still want container ergonomics.

The numbers tell the tradeoff plainly. Effective start lands around 300–800 ms once the Sentry is up. CPU overhead is modest (~10%), but I/O-heavy workloads pay 10–50% because every read, write, and futex round-trips through the interceptor. Memory overhead is roughly 50 MB per sandbox for the Sentry itself. Isolation is strong against the classic container-escape repertoire — the workload never speaks raw syscalls to the host kernel — but it is not a hardware boundary: a Sentry bug is a host-kernel-adjacent bug, and the CVE record treats it that way.

Why pick rung 2 over rung 1, then? Two reasons, both visible in the market. First, compatibility: if your preview path must run arbitrary Dockerfiles with arbitrary base images, gVisor slots under your existing container tooling where Firecracker demands a template pipeline. Second, accelerators: Modal's gVisor fleet serves everything from T4s to H100s with per-second billing, filesystem snapshots, and 50K-plus concurrency — the standout option for batch agent fleets where the workload is inference, not a Vite dev server. For generated web apps, rung 1's boundary is strictly better; for generated GPU jobs, rung 2 is where the mature product actually exists.

One footnote for completeness: Kata Containers sits between these rungs — a full VM per pod behind a standard container API, booting in ~125–500 ms depending on hypervisor. It is the right answer when you need hardware isolation without leaving the Kubernetes scheduler, and Daytona's Kata support shows vendors hedging exactly that way. It complicates the ladder, which is why it is a footnote and not a rung.

Rung 3: Docker plus seccomp — the baseline that is only safe after review

Plain Docker with a tight seccomp profile and AppArmor (or SELinux) confinement starts in ~20 ms with ~1% overhead and runs anything. It also shares the host kernel with every other tenant, so its isolation is precisely as strong as the kernel's syscall surface plus the correctness of your profiles. For code a model just wrote, that is not isolation — it is optimism with a config file.

This rung still belongs in the survey because it is the correct answer for the second half of the pipeline: code a human reviewed and tests passed on, promoted from preview to a real deployment. At that point the threat model changes from "arbitrary malicious code" to "ordinary buggy code," and paying microVM overhead per deploy buys nothing. The honest mapping — and the one the products above implement, whether they say so or not — is rung 1 for untrusted preview, rung 3 for reviewed workloads, with rung 2 covering the GPU and compatibility cases that fit neither.

The owned-hardware math: when a Hetzner box beats per-second billing

Rented sandboxes price executions; owned hardware prices capacity. The crossover is pure arithmetic, so here it is with public list prices on both sides.

On the rented side, take the E2B-class rate of ~$0.05 per vCPU-hour. A 30-minute single-vCPU agent run costs ~$0.025; a heavier 4-vCPU, 30-minute session costs ~$0.10. On the owned side, a Hetzner AX41 (6 cores / 12 threads, 64 GB RAM, NVMe) lists around €39/month and an AX52 (8 cores / 16 threads, 64 GB DDR5) around €64/month, each with 20 TB of included traffic.

Divide the box by the run: an ~€39 AX41 (≈$42) pays for itself against $0.025 preview runs at roughly 1,600–1,700 runs per month — about 55 per day. Against heavier $0.10 sessions, the crossover drops to ~420 sessions a month, or ~14 per day. Below that volume, rented sandboxes win because idle capacity costs you nothing; above it, the box wins because idle capacity on hardware you already pay for also costs you nothing, and the marginal run is free.

Three sensitivity notes before anyone budgets off this paragraph. First, concurrency: the breakeven above assumes runs serialize onto spare threads; a launch-day spike of 200 concurrent previews needs either over-provisioned hardware or burst-to-rented overflow. Second, utilization shape: preview traffic is diurnal, and a box sized for the 3 p.m. peak idles at 3 a.m. — rented sandboxes absorb that variance by construction. Third, the box is not just sandbox capacity: the same AX41 also runs your control plane, registries, and reviewed workloads, which spreads its fixed cost across line items the per-execution bill never touches. The realistic architecture for a small self-hosted platform is therefore hybrid — owned hardware as the base layer, rented microVMs as the burst valve — and the breakeven math tells you where to set the valve, not which side to pick exclusively.

Which rung a self-hosted preview path actually needs

Pulling the survey into a decision:

  • Untrusted model output, no human in the loop yet → rung 1. A deploy-from-chat preview that executes whatever the model emitted needs a guest kernel between that code and your fleet. Self-hosted Firecracker on your own Hetzner machines is a real option here — the primitive is open source and the per-run cost on owned hardware is the electricity you already pay — but budget the orchestration work (snapshots, networking, pool warming) that E2B and Daytona productize.
  • GPU-bearing or Dockerfile-arbitrary agent workloads → rung 2. gVisor's compatibility and Modal's GPU fleet exist because rung 1's template model fights both. If your agent story includes "run my training script," start here.
  • Reviewed, tested, promoted → rung 3. Ordinary containers with tight profiles are the right cost and complexity for code that already passed review. Spending microVM overhead here is security theater with a per-second meter.
  • Static frontend preview with no backend → rung 0. bolt.new's WebContainer bet is a reminder that the cheapest sandbox is the user's own browser. If the generated artifact is a static site, server-side isolation is solving a problem you do not have.

The through-line: the products that do generated-code execution well never sandbox with process restrictions alone. They put real isolated compute — a microVM, a filtered kernel, at minimum a profiled container on someone else's kernel — between model output and infrastructure. The rung is chosen by trust level, and trust level changes as code moves from prompt to production. Build the pipeline so the rung can change with it.

The trust-ladder framing generalizes: every untrusted-code path on a self-hosted platform — deploy previews, agent sandboxes, eval jobs — wants its rung chosen by who wrote the code, not by what the code claims to do. 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.

Related articles

Give your agents a chain backend

Autonomous agents hit RPC endpoints very differently than people do. See what bex router handles on their behalf.

Read the agents guide