Sitemap

Rust(wasm): On-Premise workerd-runtime(Cloudflare-style)

6 min readOct 20, 2026

Hi everybody!

Here-is a simple, logical outline in text-format(a data flow) that explains exactly how an HTTP-request travels from the outside into [y]our Rust-code(index.wasm) and back, using the `workerd`-architecture:

[ User / Browser ]
│
│ (1) Sends HTTP Request (e.g., GET /api/data)
▼
┌────────────────────────────────────────────────────────────┐
│ YOUR SERVER (On-Premises) │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ workerd │ │
│ │ (Runtime started with config.capnp configuration) │ │
│ │ │ │
│ │ Receives the Request and forwards it to: │ │
│ │ ┌────────────────────────────────────────────┐ │ │
│ │ │ V8 Isolate-Sandbox │ │ │
│ │ │ │ │ │
│ │ │ (2) index.js(JavaScript Glue-Code) │ │ │
│ │ │ │ Maps JS objects from V8 │ │ │
│ │ │ │ (Request, Headers) to types │ │ │
│ │ │ │ compatible with WebAssembly. │ │ │
│ │ │ ▼ │ │ │
│ │ │ (3) index.wasm(Your Rust-Code) │ │ │
│ │ │ │ │ │ │
│ │ │ │ Executes logic from workers-rs. │ │ │
│ │ │ │ Processes data rapidly. │ │ │
│ │ │ ▼ │ │ │
│ │ │ (4) Returns a binary-Response │ │ │
│ │ │ │ │ │
│ │ └───┼────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ (5) Converts the binary into an HTTP-Response │ │
│ └──────┼───────────────────────────────────────────────┘ │
│ │ │
└─────────┼──────────────────────────────────────────────────┘
│
▼ (6) Sends the Response back(e.g., 200 OK, JSON)
[ User / Browser ]

You can run Cloudflare(CF) Workers(using the workers-rs SDK, to write your logic, over your data, in your Rust wasm-code) locally or on-premises(on-prem) by using workerd — the official, open-source, V8-based runtime created-by Cloudflare(CF). Since workers-rs compiles code natively into WebAssembly(wasm32), it does not rely on Cloudflare’s cloud infrastructure to execute.

Below, you will find how-to configure a local-execution environment on your own-machine or within a local/on-premise infrastructure):

1. Local development and testing(Wrangler & Miniflare)

The simplest-way to run code locally during development is by using the official Cloudflare-CLI, called Wrangler. It launches a local-instance of `workerd` in the background(via Miniflare):
1-a). Scaffolding: Generate the Rust-project

cargo generate cloudflare/workers-rs

1-b). Local execution: Launch the local-server, which will listen-on localhost:8787(by default)

npx wrangler dev

Note: As of recent versions of the Cloudflare Workers docs, the `wrangler dev`- command runs the code entirely-locally on [y]our machine by-default (without routing traffic through Cloudflare-servers), using the native `workerd`- runtime.

2. On-premises hosting in-production(by using directly the native `workerd` as runtime)

If you wish-to completely-eliminate your dependency-on the Cloudflare-platform and run your Rust-compiled worker on [y]our own on-premises servers in a production-environment, you must-use the `workerd` binary directly.

2-a) Compiling the project: Generate the .wasm binary using the Rust-toolchain

# Using worker-build from the workers-rs ecosystem
npx worker-build --release

This will generate a WebAssembly file and optionally a binding JavaScript “glue” file (generated-by wasm-bindgen).

2-b) Configuring workerd: Create a configuration-file named config.capnp (which uses the Cap’n Proto protocol) to define how workerd will route requests to [y]our WASM file.

2-c) Running the server: Execute the runtime on your local server

workerd serve config.capnp

Important Technical-Considerations:

  • Async/Threading Limitations: The `workers-rs` SDK is designed-for the cooperative, single-threaded architecture specific-to V8. You cannot use standard Rust async runtimes that require multi-threading (such as the default `#[tokio::main]` macro). Instead, you must use the `#[event(fetch)]` macro provided by the `worker` crate.
    • Data-Storage(KV, D1, Durable-Objects): If you are running entirely on-prem, cloud-services such as Cloudflare KV or the D1 database will be simulated locally(using SQLite as the underlying local-storage, managed automatically by the runtime).

Remark:

  • The workerd it is not a runtime for standard native binaries(such-as .exe files on Windows or ELF files on Linux).
  • The workerd is a runtime designed specifically-for JavaScript(JS), TypeScript(TS), and WebAssembly(WASM).

Here is how it actually-works in the context-of your Rust code:

Get Ion’s stories in your inbox

Join Medium for free to get updates from this writer.

1. What does `workerd` actually execute?

When you use `workers-rs`, your Rust-written code is not compiled into a native binary for the server’s processor(x86_64 or ARM). Instead, it is compiled into WebAssembly(.wasm).
• Based on V8: `workerd` is built-upon Google’s V8-engine (the same engine used in Google Chrome and Node.js).
• Isolates: Rather-than launching a full operating-system(OS) process for each application, it utilizes a technology-called “V8 Isolates”. This technology(“V8 Isolates”) allows it(`workerd`) to run thousands-of applications simultaneously, with extremely-low memory- consumption and near-instant startup(zero cold start).

2. How-does Rust run within `workerd`(as runtime)?

The process-by which Rust code ends up running in `workerd` is as follows:
2-a). The Rust code is translated-by the compiler into WebAssembly bytecode(target: `wasm32`).
2-b). A small JavaScript file(automatically generated-by `wasm-bindgen`) acts-as a “bridge”(glue-code) between `workerd` and the WebAssembly- module.
2-c). `workerd` loads this JavaScript-script, which, in-turn, instantiates and executes the WebAssembly-code compiled-from Rust(rs2wasm).

Difference compared-to a native-binary runtime:

If you need-to run a native Rust binary(compiled-directly for the operating system/OS), `workerd` is not the right tool. For native, on-premise binaries, standard-alternatives(as/for runtime) include:

  • A minimal Docker container.
  • A system-service(such-as `systemd` on Linux).
  • Runtimes specific to micro-VMs (such-as AWS’s Firecracker).

The workerd is ideal only if you wish to maintain the exact same behavior, APIs, and performance offered-by the Cloudflare Workers platform, but on your own infrastructure.

After compiling a workers-rs project using the official command `npx worker-build — release` (which internally uses `wasm-pack` and `wasm-bindgen`), the final production artifacts are generated in a folder named `build/` (or `dist/`, depending on the configuration in `wrangler.toml`).
The exact-structure of the folder generated for production looks-like this:

📂 Structure-of the resulting files(build/):

my-worker-project/
├── build/
│ ├── index.js # The "glue" JavaScript file (the connecting bridge)
│ └── index.wasm # The Rust code compiled into WebAssembly
├── src/ # The Rust source code (.rs)
├── Cargo.toml # The Rust project configuration
└── wrangler.toml # The Cloudflare / workerd configuration

🔍 What-does each important-file contain?

1. 📄 index.js (JavaScript Glue-Code)

This is the main file that workerd will read. Since the V8-engine doesn’t natively-know how-to map complex Rust data-types(like strings, structs, or HTTP-requests) to JavaScript types, this file does the translation.
• It imports the .wasm module.
• Contains the “internal mechanics”-functions generated-by wasm-bindgen.
• Exposes the fetch event listener function that workerd calls when it(workerd) receives an HTTP-request, routing-it further-to the Rust-code.

2. 📄 index.wasm(WebAssembly binary-module)

This is the “engine” of [y]our application — all the Rust-code you wrote, along-with the dependencies-in Cargo.toml, optimized and compiled into a compact binary bytecode format.
• It(index.wasm) is a binary, non-text file(if you open it/index.wasm in an editor, you will-see hexadecimal characters).
• It(index.wasm) is completely-isolated, running in the secure WebAssembly sandbox inside-the workerd.

⚙️ How-does wrangler.toml or workerd see them(index.js and index.wasm)?

In-order for these two files to work-together at/@ runtime, they are linked in the configuration file(wrangler.toml). In wrangler.toml, the build-section usually looks-like this:

name = "my-rust-worker"
main = "build/index.js" # Tells workerd to run the JS file first

[build]
command = "npx worker-build --release"

When you start npx wrangler dev or run workerd serve, the runtime loads index.js, which-loads the index.wasm binary into memory, and from that-moment the Rust-code is ready-to respond-to network-requests.

Enjoy!

That is all! Bye…Bye!