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

-Xmx / -Xms; container-aware (+UseContainerSupport).

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 --init flag 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#