# How to Deploy 65 WASM Edge Modules on ESP32 Using WASM3 Runtime with RuView

> Deploy 65 WASM edge modules on ESP32 using WASM3 runtime and RuView. Compile WASM, flash firmware, and upload binaries via HTTP API. Maximize your ESP32 edge computing power.

- Repository: [rUv/RuView](https://github.com/ruvnet/RuView)
- Tags: how-to-guide
- Published: 2026-03-08

---

**Deploy 65 WebAssembly edge modules to an ESP32-S3 by compiling them to `wasm32-unknown-unknown`, flashing the WASM3-enabled firmware, and uploading binaries via the HTTP API on port 8032.**

RuView provides a **Tier-3 programmable-sensing layer** that runs hot-loadable WASM edge modules directly on ESP32-S3 microcontrollers using the lightweight **WASM3 interpreter**. This architecture allows you to deploy up to 65 distinct edge modules—such as the reference "6S" collection including `sig_flash_attention` and `spt_micro_hnsw`—for sub-5 millisecond on-device inference without rebooting the hardware.

---

## Build WASM Edge Modules for ESP32 Deployment

### Install the WASM32 Target

Before compiling the RuView edge modules, add the WebAssembly target to your Rust toolchain:

```bash
rustup target add wasm32-unknown-unknown

```

### Compile the Edge Module Collection

RuView organizes its 65 WASM modules within the `wifi-densepose-wasm-edge` crate. Build the entire collection or specific subsets using Cargo:

```bash
cargo build \
    --release \
    --package wifi-densepose-wasm-edge \
    --target wasm32-unknown-unknown

```

The compiler outputs `.wasm` binaries to:

```

target/wasm32-unknown-unknown/release/

```

Key modules in the 6S reference set include:
- **`sig_flash_attention.wasm`** – Budget-constrained attention mechanism (≤ 5 ms) defined in [`src/sig_flash_attention.rs`](https://github.com/ruvnet/RuView/blob/main/src/sig_flash_attention.rs)
- **`sig_coherence_gate.wasm`** – Lightweight coherence gate (≤ 2 ms) from [`src/sig_coherence_gate.rs`](https://github.com/ruvnet/RuView/blob/main/src/sig_coherence_gate.rs)
- **`spt_micro_hnsw.wasm`** – On-device approximate nearest neighbor search in [`src/spt_micro_hnsw.rs`](https://github.com/ruvnet/RuView/blob/main/src/spt_micro_hnsw.rs)
- **`spt_spiking_tracker.wasm`** – Bio-inspired tracking system in [`src/spt_spiking_tracker.rs`](https://github.com/ruvnet/RuView/blob/main/src/spt_spiking_tracker.rs)
- **`tmp_pattern_sequence.wasm`** – Daily routine pattern detector in [`src/tmp_pattern_sequence.rs`](https://github.com/ruvnet/RuView/blob/main/src/tmp_pattern_sequence.rs)
- **`tmp_goap_autonomy.wasm`** – GOAP planner for autonomous sensing in [`src/tmp_goap_autonomy.rs`](https://github.com/ruvnet/RuView/blob/main/src/tmp_goap_autonomy.rs)

---

## Flash ESP32 Firmware with WASM3 Runtime

### Enable WASM Support in ESP-IDF

The RuView firmware located in `firmware/esp32-csi-node` requires the WASM3 component. Enable it via menuconfig:

```bash
cd firmware/esp32-csi-node

idf.py menuconfig

# Navigate to: Component config → WASM3 → Enable (CONFIG_WASM_ENABLE=y)

```

The WASM3 interpreter is fetched and compiled via [`components/wasm3/CMakeLists.txt`](https://github.com/ruvnet/RuView/blob/main/components/wasm3/CMakeLists.txt), which pulls the upstream source and links it into the ESP32 image.

### Build and Flash the Firmware

Compile the firmware and flash it to the ESP32-S3:

```bash
idf.py build flash monitor

```

Critical runtime components include:
- **[`main/wasm_runtime.c`](https://github.com/ruvnet/RuView/blob/main/main/wasm_runtime.c)** – Initializes the WASM3 environment, allocates **160 KB PSRAM arenas** per module slot, and dispatches `process_frame` calls at approximately 20 Hz
- **[`main/wasm_upload.c`](https://github.com/ruvnet/RuView/blob/main/main/wasm_upload.c)** – Implements the HTTP REST API on **port 8032** for module management

After flashing, the device listens for WASM uploads on TCP port 8032.

---

## Deploy WASM Modules to the ESP32 Edge

### Upload Binaries via HTTP API

RuView exposes a lightweight HTTP API for hot-loading modules. You can deploy using the provided Python helper or manual `curl` commands.

**Using the Python deployment script:**

```bash
python scripts/esp32_wasm_test.py \
    --port /dev/ttyUSB0 \
    --modules \
        target/wasm32-unknown-unknown/release/sig_flash_attention.wasm \
        target/wasm32-unknown-unknown/release/sig_coherence_gate.wasm \
        target/wasm32-unknown-unknown/release/spt_micro_hnsw.wasm \
        target/wasm32-unknown-unknown/release/spt_spiking_tracker.wasm \
        target/wasm32-unknown-unknown/release/tmp_pattern_sequence.wasm \
        target/wasm32-unknown-unknown/release/tmp_goap_autonomy.wasm

```

**Manual upload with curl:**

```bash
ESP_IP="192.168.1.42"
ESP_PORT="8032"

for module in sig_flash_attention sig_coherence_gate spt_micro_hnsw \
              spt_spiking_tracker tmp_pattern_sequence tmp_goap_autonomy; do
    curl -X POST "http://${ESP_IP}:${ESP_PORT}/wasm/upload?name=${module}" \
         -H "Content-Type: application/octet-stream" \
         --data-binary @target/wasm32-unknown-unknown/release/${module}.wasm
done

```

### Start and Manage Modules

After uploading, activate individual modules using the start endpoint:

```bash

# Start a specific module

curl -X POST "http://${ESP_IP}:${ESP_PORT}/wasm/start?name=sig_flash_attention"

# Verify running modules

curl http://${ESP_IP}:${ESP_PORT}/wasm/list

```

The list endpoint returns JSON metadata:

```json
{
  "modules": [
    {"name": "sig_flash_attention", "size": 12345, "status": "running"},
    {"name": "spt_micro_hnsw", "size": 9876, "status": "running"}
  ]
}

```

To stop or remove modules:

```bash

# Stop a module

curl -X POST "http://${ESP_IP}:${ESP_PORT}/wasm/stop?name=sig_flash_attention"

# Delete a module

curl -X POST "http://${ESP_IP}:${ESP_PORT}/wasm/delete?name=sig_flash_attention"

```

---

## Runtime Architecture and Memory Constraints

RuView’s WASM3 integration enforces strict resource budgets suitable for ESP32-S3 constraints. Each deployed module operates within a **160 KB PSRAM arena** allocated by [`wasm_runtime.c`](https://github.com/ruvnet/RuView/blob/main/wasm_runtime.c), ensuring isolation between the 65 potential edge modules.

The runtime invokes each module’s `process_frame` function at the DSP tick rate (approximately 20 Hz). Latency annotations in the source code—such as "Budget: S (< 5 ms)" in [`sig_flash_attention.rs`](https://github.com/ruvnet/RuView/blob/main/sig_flash_attention.rs)—guarantee that modules complete inference within their allocated time slices. The WASM3 interpreter’s **Tier-3** classification indicates these are hot-loadable, sandboxed algorithms that execute directly on the edge device without cloud dependency.

Host API functions exposed to WASM modules include `csi_get_frame` for accessing pre-processed CSI data and `csi_emit_event` for publishing results back to the RuView pipeline, as implemented in the runtime glue layer.

---

## Summary

- **RuView** enables deployment of **65 WASM edge modules** on ESP32-S3 microcontrollers using the **WASM3 interpreter** for sub-5 ms on-device inference.
- Build modules by compiling the `wifi-densepose-wasm-edge` crate to `wasm32-unknown-unknown` and locating outputs in `target/wasm32-unknown-unknown/release/`.
- Flash firmware from `firmware/esp32-csi-node` with `CONFIG_WASM_ENABLE=y` to embed the WASM3 runtime and HTTP upload API on port 8032.
- Deploy binaries using [`scripts/esp32_wasm_test.py`](https://github.com/ruvnet/RuView/blob/main/scripts/esp32_wasm_test.py) or direct `curl` POST requests to `/wasm/upload`, then activate via `/wasm/start`.
- Each module runs in an isolated **160 KB PSRAM arena** with guaranteed latency budgets, invoked at 20 Hz through the `process_frame` host API.

---

## Frequently Asked Questions

### How many WASM modules can run simultaneously on ESP32-S3?

RuView supports **up to 65 distinct WASM edge modules** in the collection, with the runtime capable of loading multiple modules simultaneously depending on available PSRAM. Each active module consumes a **160 KB PSRAM arena** allocated by [`wasm_runtime.c`](https://github.com/ruvnet/RuView/blob/main/wasm_runtime.c), so practical limits depend on your ESP32-S3’s total PSRAM capacity and the specific subset of modules deployed.

### What is the maximum binary size for each WASM edge module?

While the RuView architecture does not enforce a hardcoded binary size limit, modules must fit within the **160 KB PSRAM arena** allocated per slot at runtime, as defined in [`firmware/esp32-csi-node/main/wasm_runtime.c`](https://github.com/ruvnet/RuView/blob/main/firmware/esp32-csi-node/main/wasm_runtime.c). Additionally, modules must adhere to their annotated latency budgets—typically **sub-5 ms** for standard modules and **sub-2 ms** for lightweight gates—to maintain the 20 Hz DSP tick rate.

### Can I hot-swap WASM modules without rebooting the ESP32?

Yes. The HTTP API implemented in [`firmware/esp32-csi-node/main/wasm_upload.c`](https://github.com/ruvnet/RuView/blob/main/firmware/esp32-csi-node/main/wasm_upload.c) supports **hot-loading** via the `/wasm/upload`, `/wasm/start`, `/wasm/stop`, and `/wasm/delete` endpoints. You can upload new binaries, start additional modules, or replace running instances dynamically without reflashing the firmware or power-cycling the device, enabling true Tier-3 programmable sensing at the edge.

### Which Rust target is required for RuView edge modules?

All RuView edge modules must compile to the **`wasm32-unknown-unknown`** target. This target produces bare-metal WebAssembly binaries without system dependencies, suitable for the WASM3 interpreter running on ESP32-S3. Add the target via `rustup target add wasm32-unknown-unknown` and build using `cargo build --release --target wasm32-unknown-unknown` as specified in [`docs/build-guide.md`](https://github.com/ruvnet/RuView/blob/main/docs/build-guide.md).