Skip to content

Binaryen and wasm-opt

Binaryen is Google’s optimising compiler infrastructure for WebAssembly. Its most widely used tool is wasm-opt, which takes an existing .wasm binary and rewrites it to produce a smaller or faster output. You do not need to understand Binaryen’s internal IR to benefit from it — a single command can cut 20–40 % off a release binary.

wasm-opt applies a sequence of compiler passes: dead-code elimination, constant folding, function inlining, local CSE, and many more. It works entirely on the binary level — it does not need the original source or any metadata.

Terminal window
# Install globally via npm
npm install -g binaryen
# Or install via Homebrew on macOS
brew install binaryen

wasm-opt uses the same level flags as Clang/GCC:

Terminal window
# -O1 — light optimisation (fast build)
wasm-opt -O1 input.wasm -o output.wasm
# -O2 — balanced (same as release builds in most toolchains)
wasm-opt -O2 input.wasm -o output.wasm
# -O3 — aggressive (maximise speed, larger code possible)
wasm-opt -O3 input.wasm -o output.wasm
# -Os — optimise for size (speed is secondary)
wasm-opt -Os input.wasm -o output.wasm
# -Oz — maximise size reduction (slowest optimisation)
wasm-opt -Oz input.wasm -o output.wasm

For most production deployments, -Oz offers the best trade-off: smaller download, faster parse, warm cache.

In practice you rarely call wasm-opt directly. These popular toolchains invoke it automatically in release mode:

ToolchainWhen it runs wasm-opt
Emscripten-O2 / -O3 release flags
wasm-pack (Rust)wasm-pack build --release
AssemblyScriptasc --optimize
Go (TinyGo)-opt=z flag

If you are consuming a .wasm from any of these, the binary is probably already optimised. Running wasm-opt a second time is safe but yields diminishing returns.

Terminal window
# Strip the DWARF debug section (reduces size, loses stack traces)
wasm-opt -Oz --strip-dwarf input.wasm -o output.wasm
# Strip all custom sections
wasm-opt -Oz --strip-producers input.wasm -o output.wasm
# Print module statistics before and after
wasm-opt -Oz --print-stats input.wasm -o output.wasm
# Keep a name section for readable stack traces
wasm-opt -Oz --debuginfo input.wasm -o output.wasm

Always measure before and after. A quick bash one-liner shows the size difference:

Terminal window
wasm-opt -Oz input.wasm -o output.wasm
echo "Before: $(wc -c < input.wasm) bytes"
echo "After: $(wc -c < output.wasm) bytes"
Which wasm-opt flag maximises binary size reduction?
Do you need the original source code to run wasm-opt?
Which toolchain calls wasm-opt automatically during a release build?
What does --strip-dwarf do?