Evaluating Go's WebAssembly Compiler and Runtime Support: A Technical Report
Key points
- Go has official Wasm support since Go 1.11 (
GOOS=js GOARCH=wasm) and WASI Preview 1 support since Go 1.21 (GOOS=wasip1), enabling execution in runtimes such as Wasmtime, WasmEdge, and Wasmer without a JavaScript host. - Go 1.24 adds the
go:wasmexportdirective and WASI reactor mode: when built with-buildmode=c-shared, the compiler emits an_initializefunction instead of_start, letting hosts call exported Go functions repeatedly without reinitializing the runtime. - Type restrictions on
go:wasmexport/go:wasmimportwere relaxed in Go 1.24, allowing strings and pointers to host-layout structs (which must embedstructs.HostLayout). - Most Go features and the standard library work under Wasm, including goroutines and the GC — but Wasm is currently single-threaded, so goroutines are cooperatively scheduled and a blocking host call stalls all goroutines.
- Browser hosts load modules via
WebAssembly.instantiate/instantiateStreamingwith Go'swasm_exec.jsbridge; Go code interacts with JavaScript and the DOM through thesyscall/jspackage. - WASI Preview 1 limits network sockets to pre-opened ones, so servers cannot be created directly; third-party libraries like
github.com/stealthrocket/network around this. - Performance: cited benchmarks show Go-compiled Wasm runs ~13x slower than native Go, versus ~4x for Rust. Standard Go compiler output includes the full runtime, producing large binaries; TinyGo produces much smaller modules (with some standard-library gaps) and experimentally supported
go:wasmexportbefore Go 1.24. - Advantages: near-native speed, portability across browser/server/edge/embedded, static typing, sandboxed security, and strong official plus community support (TinyGo, Vugu, Vecty).
- Disadvantages: large binary size, measurable performance overhead versus native, no true parallelism, extra ecosystem integration work, and a learning curve for JavaScript-first teams.
- Outlook: Wasm threading and GC proposals will benefit Go's concurrency model and reduce overhead; a more complete WASI will expand network, database, and device access — positioning Go/Wasm for browser apps, plugins, serverless, and edge/IoT computing.
GOOS=js GOARCH=wasmtargets browsers (requireswasm_exec.js);GOOS=wasip1targets WASI runtimes.- Go 1.24's reactor mode enables persistent plugin-style Wasm services instead of one-shot commands.
- Tools like
wasmbrowsertestlet developers run Go tests in a browser. - Browser: all major engines support Wasm; deployment is simple (HTML + JS glue) but the environment is sandboxed with simulated file/network access.
- WASI runtimes: Wasmtime, WasmEdge, Wasmer host Go WASI binaries; WasmEdge targets cloud-native, edge, and IoT use with extension support (AI inference, databases).
- Wasm cold starts are far faster than containers, often milliseconds — attractive for FaaS and edge scenarios.
- Binary size: full Go runtime inflates module size to megabytes; TinyGo and compiler-option tuning (disabling unused scheduler/GC features) reduce size and memory overhead.
- The Wasm GC proposal (late-stage) should reduce Go runtime memory-management overhead and module size; threading support would unlock true parallelism for goroutines.
- WASI beyond Preview 1 will standardize networking, database, and device access, strengthening Go's role in edge microservices and IoT functions.
Detailed findings
Compiler support
Runtime environments
Performance and size
Application scenarios
1. Browser applications: reuse backend Go logic in the frontend; frameworks like Vugu and Vecty offer component-based UI development in Go; challenges include binary size, JS toolchain integration, and DOM access only via syscall/js.
2. Cross-platform development: one Wasm binary can run on Linux, Windows, mobile, and browsers wherever a Wasm runtime exists; challenges include runtime availability and platform-specific host-interface differences.
3. Edge computing: millisecond cold starts, sandboxed isolation for third-party/multi-tenant code, and small footprint make Go/Wasm ideal for IoT gateways and edge functions; hurdles include runtime deployment, network/IO support in WASI, and lifecycle tooling.