# NanVix MicroVM vs Hyperlight Backends: Isolation Strategies in Microsoft MXC

> Explore NanVix MicroVM vs Hyperlight backends in Microsoft MXC. Understand isolation strategies and discover how NanVix uses Hypervisor Platform and Hyperlight runs in-process Unikernel for faster startup.

- Repository: [Microsoft/mxc](https://github.com/microsoft/mxc)
- Tags: deep-dive
- Published: 2026-06-07

---

**Microsoft MXC provides two mutually exclusive MicroVM containment backends—NanVix spawns a separate Windows Hypervisor Platform process with full kernel boot overhead, while Hyperlight runs an in-process Unikernel via Rust library integration for significantly faster startup.**

The `microsoft/mxc` repository implements multiple sandboxing strategies for secure code execution, with the **NanVix MicroVM and Hyperlight backends** representing two distinct approaches to micro-virtualization. Both backends expose the same `ContainmentBackend` interface to `wxc-exec`, but they differ fundamentally in process isolation, startup latency, and supported security policies.

## Execution Model: Separate Process vs In-Process

### NanVix: Full Micro-Kernel VM

The NanVix backend spawns a **separate process** (`nanvixd.exe`) that runs a full micro-kernel inside the **Windows Hypervisor Platform (WHP)**. According to the implementation in [[`src/backends/nanvix/runner/src/lib.rs`](https://github.com/microsoft/mxc/blob/main/src/backends/nanvix/runner/src/lib.rs)](https://github.com/microsoft/mxc/blob/main/src/backends/nanvix/runner/src/lib.rs), this launches a lightweight Linux-like kernel that boots a complete guest OS.

### Hyperlight: Library-Based Unikernel

In contrast, the Hyperlight backend loads the `hyperlight-unikraft-host` **library in-process** within `wxc-exec`. As implemented in [[`src/backends/hyperlight/common/src/lib.rs`](https://github.com/microsoft/mxc/blob/main/src/backends/hyperlight/common/src/lib.rs)](https://github.com/microsoft/mxc/blob/main/src/backends/hyperlight/common/src/lib.rs), the micro-VM runs as a Rust object inside the same process using the **Unikraft Unikernel** framework.

## Startup Latency and Performance

Cold starts differ dramatically between the two implementations.

**NanVix** requires a full VM boot sequence with an approximate **60-second timeout** for cold starts. While warm-started CBOR snapshots (created via `--setup-microvm`) reduce this to a few hundred milliseconds, each execution still incurs WHP launch overhead.

**Hyperlight** eliminates VM boot overhead entirely. Because the Unikernel runs in-process, startup completes in **tens of milliseconds**. The warm-start concept does not apply here; the micro-VM image loads once and remains reused across executions.

## Artifact Provenance and Distribution

Distribution models reflect the architectural split:

- **NanVix** ships pre-built binaries (`nanvixd.exe`, `kernel.elf`, `python3.initrd`, `nanvix_rootfs.img`) as separate files adjacent to the executable. The setup command warms a CBOR snapshot specific to Windows environments.
- **Hyperlight** pulls the micro-VM image from a container registry (`ghcr.io/hyperlight-dev/...`) via the `hyperlight-common` crate. No separate binaries ship with the distribution; the image unpacks automatically at setup time via `--setup-hyperlight`.

## Network and Filesystem Policies

Security policies map differently to each backend's capabilities.

### Network Isolation

**NanVix** provides **no network stack**—the micro-VM remains completely isolated. The implementation explicitly rejects `networkPolicy` and `networkProxy` configurations with `ERR_NETWORK_POLICY` and `ERR_PROXY_POLICY` errors.

**Hyperlight** exposes a network stack via Unikraft but disables proxying. While it supports a limited set of network policies, `networkProxy` requests still generate errors.

### Filesystem Restrictions

Both backends enforce strict namespace isolation. The guest observes only its own rootfs image; host paths remain inaccessible (`ERR_DENIED_PATHS`).

**NanVix** interprets `readwrite_paths` and `readonly_paths` as mount points inside the guest kernel. **Hyperlight** enforces similar restrictions but explicitly does not support `workingDirectory` (`ERR_WORKDIR`).

## I/O Handling and Error Management

Standard stream handling diverges based on process architecture.

**NanVix** closes `stdin` (`Stdio::null`) by default while inheriting `stdout` and `stderr`. When the environment variable `MXC_NANVIX_TRACE=1` is set, the runner captures `stderr` for diagnostic logging.

**Hyperlight** uses the host process's standard streams directly. The SDK must explicitly set `usePty: false` since PTY mode is unsupported.

Error classification also differs:

- **NanVix** categorizes failures into `NanVixError::Preflight`, `Platform`, `Runtime`, and `Timeout`, returning `ScriptResponse` with sentinel exit code `-1`.
- **Hyperlight** wraps errors via `hyperlight_common` as `HyperlightError`, surfacing generic non-zero exit codes.

## Configuration and Platform Support

Both backends gate compilation via conditional compilation flags in the source.

### Platform Constraints

- **NanVix** builds only on **Windows x86_64** with WHP enabled, gated by `#[cfg(all(feature = "microvm", target_os = "windows"))]`.
- **Hyperlight** targets **x86_64** (`#[cfg(all(feature = "hyperlight", target_arch = "x86_64"))]`) but supports both Windows and Linux for the host process.

### JSON Configuration

The parser in [[`src/core/wxc_common/src/config_parser.rs`](https://github.com/microsoft/mxc/blob/main/src/core/wxc_common/src/config_parser.rs)](https://github.com/microsoft/mxc/blob/main/src/core/wxc_common/src/config_parser.rs) maps containment strings to the `ContainmentBackend` enum defined in [[`src/core/wxc_common/src/models.rs`](https://github.com/microsoft/mxc/blob/main/src/core/wxc_common/src/models.rs)](https://github.com/microsoft/mxc/blob/main/src/core/wxc_common/src/models.rs):

```json
// NanVix MicroVM
{ "containment": "microvm" }

// Hyperlight
{ "containment": "hyperlight" }

```

The CLI entry point in [[`src/core/wxc/src/main.rs`](https://github.com/microsoft/mxc/blob/main/src/core/wxc/src/main.rs)](https://github.com/microsoft/mxc/blob/main/src/core/wxc/src/main.rs) dispatches to `NanVixScriptRunner::new()` or `HyperlightScriptRunner::new()` via boxed trait objects.

## Implementation Examples

### Running Scripts in NanVix

Configure the containment method and warm the snapshot before execution:

```json
{
  "process": { "commandLine": "print('Hello from NanVix!')" },
  "containment": "microvm"
}

```

```bash

# Optional: Warm-up the CBOR snapshot for faster subsequent runs

wxc-exec --setup-microvm

# Execute

wxc-exec script.json

```

### Running Scripts in Hyperlight

Hyperlight requires initial image setup but no warm-start concept:

```json
{
  "process": { "commandLine": "print('Hello from Hyperlight!')" },
  "containment": "hyperlight"
}

```

```bash

# Download and unpack the Unikraft image (one-time setup)

wxc-exec --setup-hyperlight

# Execute with in-process startup

wxc-exec script.json

```

### SDK Configuration (TypeScript)

Both backends appear as options in the `SandboxingMethod` type defined in [[`sdk/src/types.ts`](https://github.com/microsoft/mxc/blob/main/sdk/src/types.ts)](https://github.com/microsoft/mxc/blob/main/sdk/src/types.ts):

```typescript
import { MXC } from "mxc-sdk";

const request: MXC.ExecutionRequest = {
  process: { commandLine: "print('hello')" },
  containment: "microvm",  // or "hyperlight"
  // For Hyperlight, ensure usePty is disabled
  usePty: false
};

const result = await MXC.run(request);
console.log(result.stdout);

```

## Summary

- **NanVix MicroVM** implements **process-level isolation** via Windows Hypervisor Platform, requiring full kernel boot (~60s cold start) but providing complete network isolation through a separate `nanvixd.exe` process.
- **Hyperlight** provides **in-process isolation** via Unikraft library integration, achieving startup times in tens of milliseconds without separate binaries but with limited network policy support.
- Both backends enforce strict filesystem sandboxing and map to `ContainmentBackend::MicroVm` and `ContainmentBackend::Hyperlight` in the core models.
- **Platform support** differs: NanVix requires Windows with WHP, while Hyperlight supports Windows and Linux on x86_64.
- **Configuration** uses identical JSON keys (`"containment": "microvm"` or `"hyperlight"`) parsed in [`config_parser.rs`](https://github.com/microsoft/mxc/blob/main/config_parser.rs).

## Frequently Asked Questions

### Which backend offers better isolation security?

**NanVix provides stronger isolation** by running a full micro-kernel VM in a separate process (`nanvixd.exe`) with its own memory space and no network stack. Hyperlight runs as a library within the `wxc-exec` process, relying on Unikernel boundaries rather than hardware virtualization for containment.

### Can I use Hyperlight on Linux while NanVix requires Windows?

**Yes.** The Hyperlight backend compiles on both Windows and Linux x86_64 systems, gated by `#[cfg(all(feature = "hyperlight", target_arch = "x86_64"))]`. NanVix is restricted to **Windows x86_64 only** with the Windows Hypervisor Platform enabled.

### Why does NanVix have a 60-second timeout while Hyperlight starts instantly?

**NanVix performs a full VM boot sequence** including kernel initialization and rootfs mounting within the WHP hypervisor, justifying the 60-second timeout for cold starts. Hyperlight loads a pre-built Unikraft image in-process as a Rust object, eliminating boot overhead entirely and reducing startup to tens of milliseconds.

### How do I configure filesystem access for each backend?

Both backends map `readwrite_paths` and `readonly_paths` to guest mount points rather than host directories. **NanVix** mounts these within its Linux-like kernel, while **Hyperlight** applies them within the Unikraft namespace. Neither supports direct host path access (`ERR_DENIED_PATHS`), and Hyperlight specifically rejects `workingDirectory` configuration.