diff --git a/docs/docs/experimental/redline.md b/docs/docs/experimental/redline.md
new file mode 100644
index 000000000..74d5f335b
--- /dev/null
+++ b/docs/docs/experimental/redline.md
@@ -0,0 +1,175 @@
+---
+sidebar_position: 2
+sidebar_label: Native Compilation (Redline)
+title: Native Compilation with Redline
+---
+## Overview
+
+:::warning[Experimental]
+Redline is experimental, see [Why](why.md) for what that means for stability.
+It also supports less of the WebAssembly specification than the other execution
+modes, so check [Feature support](#feature-support) before adopting it.
+:::
+
+Redline compiles your Wasm module to native machine code using [Cranelift](https://cranelift.dev/),
+instead of to JVM bytecode. Compilation happens at build time for every supported platform, and the
+right one is selected at runtime.
+
+It is a substitute for the [Build Time Compiler](../execution/build-time-compiler.md) only, not for
+the interpreter or the [Runtime Compiler](../execution/runtime-compiler.md), and it is enabled on
+the same Maven plugin. The bytecode is still generated, and is used whenever native code cannot be.
+
+## Feature support
+
+Redline supports:
+
+* the core specification
+* bulk memory
+* tail call
+* threads and atomics
+* reference type instructions
+
+Redline does **not** support:
+
+* multi memory
+* exception handling
+* garbage collection
+* typed function references
+* SIMD
+* passing `externref` values to and from host functions
+
+If your module uses anything from the second list the build fails. There is no per function
+fallback, so a single unsupported instruction stops the whole module from compiling.
+
+Every other execution mode supports all of the above, with the exception of SIMD,
+which is available only in the interpreter.
+
+## Platform support
+
+Native code is generated for six platforms:
+
+| | x86_64 | aarch64 |
+|---|---|---|
+| **Linux** | yes | yes |
+| **macOS** | yes | yes |
+| **Windows** | yes | yes |
+
+On any other platform your module still runs, using the compiled bytecode instead. See
+[Falling back](#falling-back).
+
+## Usage
+
+Enable it on the compiler plugin:
+
+```xml
+
+ run.endive
+ endive-compiler-maven-plugin
+
+
+
+ compile
+
+
+ org.acme.wasm.MyModule
+ src/main/resources/my.wasm
+ true
+
+
+
+
+```
+
+and add a runner. This is the only dependency you need, everything else comes transitively:
+
+```xml
+
+ run.endive
+ redline-runner-experimental
+ ${endive.version}
+
+```
+
+`redline-runner-experimental` uses the Panama FFM API and requires Java 25 or later. On older
+versions use `redline-runner-jffi-experimental`, which needs only Java 11:
+
+```xml
+
+ run.endive
+ redline-runner-jffi-experimental
+ ${endive.version}
+
+```
+
+If both are present, the Panama runner is used wherever the JDK supports it.
+
+Your module is then used exactly as it would be without redline:
+
+```text
+try (var instance = MyModule.builder().build()) {
+ var f = instance.export("my_function");
+}
+```
+
+## Falling back
+
+When native code cannot be used, `builder()` falls back to the bytecode produced by the
+[Build Time Compiler](../execution/build-time-compiler.md), which is always generated alongside it.
+This happens on platforms outside the table above, or when no runner is on the classpath.
+
+Your module keeps working either way, so the fallback is silent. To check which one you got:
+
+```text
+MyModule.nativeProvider().isPresent()
+```
+
+It is `true` when native code is in use and `false` when the bytecode is. `MyModule.safeBuilder()`
+always uses the bytecode, which is useful for comparing the two.
+
+## What to expect
+
+**Jar size.** Native code is considerably larger than the Wasm it comes from, and by default one
+copy is generated per platform. If you know where you deploy, list only those targets:
+
+```xml
+
+ x86_64-unknown-linux-gnu
+
+```
+
+The available triples are `x86_64-unknown-linux-gnu`, `aarch64-unknown-linux-gnu`,
+`x86_64-apple-darwin`, `aarch64-apple-darwin`, `x86_64-pc-windows-msvc` and
+`aarch64-pc-windows-msvc`.
+
+**Build time.** Compiling for every platform takes noticeably longer than the build time compiler
+alone. Narrowing the target list helps here too.
+
+**Imported memories and tables.** A memory or table you pass in through `ImportValues` has to be
+created by the runner, otherwise the first call fails. Modules that declare their own memory,
+including anything built for WASI, are unaffected.
+
+Create it through the provider:
+
+```text
+var provider = MyModule.nativeProvider().orElseThrow();
+
+var memory = provider.createMemory(new MemoryLimits(1, 2));
+var table = provider.createImportTable(new Table(ValType.FuncRef, new TableLimits(1)), REF_NULL_VALUE);
+
+var imports = ImportValues.builder()
+ .addMemory(new ImportMemory("env", "memory", memory))
+ .addTable(new ImportTable("env", "table", table))
+ .build();
+
+try (var instance = MyModule.builder().withImportValues(imports).build()) {
+ var f = instance.export("my_function");
+}
+```
+
+
diff --git a/docs/tests/approvals/docs-experimental-redline.md.approved.txt b/docs/tests/approvals/docs-experimental-redline.md.approved.txt
new file mode 100644
index 000000000..c6cac6926
--- /dev/null
+++ b/docs/tests/approvals/docs-experimental-redline.md.approved.txt
@@ -0,0 +1 @@
+empty