Runtimes#
A runtime in the infrastructure sense is the layer that executes a deployable artifact. The OS kernel runs a process; a container runtime runs a container; a hypervisor runs a VM; a language runtime runs bytecode; a Wasm runtime runs a wasm module. Most modern systems stack several of these.
Runtimes are easy to overlook because they’re invisible when working; when something goes wrong, knowing which layer is which saves hours.
The Layers#
Layer |
Examples |
|---|---|
Application code |
The deployable artifact. |
Language runtime |
JVM, .NET CLR, V8, CPython, Go runtime. |
Container runtime |
containerd, runc, CRI-O. |
OS kernel |
Linux, BSD, Windows kernel. |
Hypervisor (optional) |
KVM, ESXi, Hyper-V, Firecracker. |
Hardware |
CPU, NIC, disks. |
A request hits the application, routes through the language runtime, which makes a syscall, which goes through the kernel, which (in cloud) runs inside a hypervisor on physical hardware. Each layer adds latency and an attack surface; each pays its rent in capabilities.
OCI Container Runtimes#
The OCI standardizes how containers run. Low-level runtimes spawn the process; higher-level runtimes wrap them with image management, networking, and lifecycle. The list below covers both layers, with containerd dominating the high-level pick in 2026.
The Open Container Initiative defines two specs: image format and runtime behavior. Multiple implementations conform.
Runtime |
Role |
|---|---|
runc |
The reference low-level OCI runtime; spawns the container process. |
crun |
C-based alternative to runc; faster startup, smaller. |
runsc / gVisor |
Intercepts syscalls in user space; stronger isolation, slower. |
kata-runtime |
Launches a lightweight VM per container; VM-level isolation with container ergonomics. |
youki |
Rust reimplementation of runc. |
These are usually wrapped by higher-level runtimes:
Runtime |
Role |
|---|---|
containerd |
The industry-standard high-level runtime; under Docker, Kubernetes, and most managed offerings. |
CRI-O |
Kubernetes-focused; thinner than containerd, OCI-only. |
Docker Engine |
Adds the docker CLI / API on top of containerd + runc. |
Podman |
Daemonless; conforms to OCI; runs containers as rootless processes. |
In Kubernetes, the runtime is configured per node via the Container Runtime Interface (CRI). Most clusters in 2026 use containerd; CRI-O appears in OpenShift and a few other distributions.
microVMs#
Lightweight VMs that boot in milliseconds, designed for serverless and multi-tenant container hosting:
microVM |
Role |
|---|---|
Firecracker (AWS) |
Powers Lambda and Fargate; Rust; KVM-based. |
Cloud Hypervisor |
Intel-led; similar role. |
NEMU / qemu-microvm |
Minimal QEMU. |
Pair with a “VM-per-container” runtime (Kata, Firecracker integration in containerd) to get VM-level isolation with sub-second startup.
Wasm Runtimes#
The newest runtime layer, gaining real footprint in 2026. Wasm trades the OCI container model for tiny startup, sandboxed-by-design execution, and a single artifact that runs in browsers, servers, edge nodes, proxies, and inside databases. Wasmtime, WasmEdge, and Wasmer lead.
Runtime |
Role |
|---|---|
Wasmtime (Bytecode Alliance) |
The reference standalone runtime. |
WasmEdge (CNCF) |
Focused on edge / IoT / serverless. |
Wasmer |
Multi-language SDKs. |
V8 |
Runs Wasm alongside JavaScript; powers Cloudflare Workers via its own deployment model. |
Spin (Fermyon) |
Application framework for serverless Wasm. |
wasmCloud |
Distributed Wasm orchestrator. |
Where Wasm runs in 2026:
Surface |
Where |
|---|---|
Edge functions |
Cloudflare Workers (V8), Fastly Compute (Wasmtime), Vercel Edge. |
Service mesh proxies |
Envoy filters as Wasm. |
Embedded scripting |
Inside databases (Neon, GreptimeDB) and apps. |
Polyfill containers |
Alternative to OCI for some workloads; significantly smaller and faster than containers. |
Wasm is not yet a full container replacement (limited threading, networking, filesystem stories), but it’s encroaching on niches where container startup time hurts.
Language Runtimes#
The runtime layer inside every process. JVMs, .NET CLRs, V8, CPython, the Go runtime; each shapes startup time, memory footprint, GC pause behavior, concurrency model, and profiler/APM compatibility. Operations work that ignores language runtime differences ends up rediscovering them.
The runtime inside the container or process:
Language |
Runtime |
|---|---|
Java / Kotlin / Scala |
JVM (HotSpot, OpenJ9, GraalVM) |
.NET (C#, F#) |
CLR (.NET, Mono) |
JavaScript / TypeScript |
V8 (Node, Bun, Deno), JavaScriptCore, SpiderMonkey |
Python |
CPython, PyPy |
Go |
Go runtime (compiled in) |
Rust / C / C++ |
native (no runtime; libc / libstdc++ only) |
Erlang / Elixir |
BEAM |
Ruby |
MRI / YARV, TruffleRuby, JRuby |
PHP |
Zend, FrankenPHP, RoadRunner |
Language runtimes affect operations far more than people expect:
Dimension |
Shape |
|---|---|
Cold-start latency |
In serverless. |
Memory footprint |
Go binaries are slim; JVM apps are heavy. |
Garbage collection pauses |
JVM tail-latency, .NET GC tuning. |
Concurrency model |
Threads vs. async / event loop vs. BEAM processes. |
Debugging surface |
Profilers and APM agents are runtime-specific. |
JVM Specifics (Worth Knowing)#
The JVM is its own ops topic:
Knob |
Shape |
|---|---|
Heap sizing |
|
Garbage collectors |
G1 (default), ZGC (low-pause), Shenandoah, Parallel. |
GraalVM native-image |
Ahead-of-time compile to native; fast start, smaller memory, longer build. |
JFR (Java Flight Recorder) |
Continuous profiling, low overhead. |
For Kubernetes, set memory requests/limits and -Xmx so the JVM
respects cgroups. Out-of-memory kills with no warning are the classic
JVM-in-K8s failure.
Process Supervisors#
The PID-1 question every container author meets. The
default is the application itself; tini and dumb-init
fix zombie reaping and signal forwarding; running systemd
inside a container is mostly a bad idea. Kubernetes
preStop hooks and termination grace matter as much.
In-container init handling matters:
Default, the container’s PID 1 is your application. Signals (SIGTERM) reach it directly; that’s good. Reaping zombies and forwarding signals correctly is on you.
tini / dumb-init, minimal init systems that fix the zombie / signal stories. Use
--initflag in Docker / Podman, or include in your Dockerfile.systemd in containers, mostly a bad idea; works but adds surface area.
For Kubernetes, preStop hooks and graceful termination periods
matter as much as the init system.
The Startup-Time Hierarchy#
A rough mental model of cold-start times in 2026:
Runtime |
Typical cold start |
|---|---|
Wasm (V8 isolate) |
<1 ms |
Edge runtime |
1-10 ms |
microVM (Firecracker) |
~125 ms |
Container (Go / Rust) |
~50-150 ms |
Container (Node / Python) |
~100-500 ms |
Container (JVM / .NET) |
0.5-3 s (without AOT) |
Full VM cold boot |
5-30 s |
Choose the runtime to match the workload. For request-per-fn at the edge, V8 isolates; for stateful long-lived apps, containers; for multi-tenant strong-isolation, microVMs.
The Runtime / Workload Match#
Workload |
Best-fit runtime |
|---|---|
Long-lived web service |
Container on Kubernetes |
Spiky / event-driven |
Serverless (microVM behind FaaS) |
Edge / personalization |
V8 isolate / Wasm |
Strong multi-tenant |
microVM (Firecracker / Kata) |
Embedded / IoT |
Wasm / native binary |
Heavy CPU / GPU |
Container with GPU passthrough on bare metal / VM |
Data-plane proxy |
Envoy / native; Wasm filters for extension |
See Also#
Containers, the OCI container side.
Virtualization, VMs and microVMs.
Serverless, managed compute that hides the runtime.
Languages, per-language runtimes.