The component model and the plugin problem
WebAssembly's most important feature isn't running fast in a browser. It's letting you run someone else's code safely.
WebAssembly's original pitch was speed in the browser. That pitch was approximately right and substantially less important than what it turned into.
The actual killer application is running untrusted code with a capability-based security model and a language-agnostic interface, and the component model is the piece that makes it usable.
the problem it solves#
Every extensible application faces the same question: how do I let third parties add functionality without letting them own my process?
The historical answers are all bad:
- Dynamic libraries. Full process access. One bad plugin corrupts everything.
- An embedded scripting language. Better isolation, but you have committed everyone to Lua or JavaScript, and the FFI boundary is a source of both bugs and escapes.
- Subprocesses with IPC. Safe and slow, with serialization overhead on every call and a lot of plumbing.
- Containers. Very safe, very heavy. Startup in the tens or hundreds of milliseconds, memory overhead per instance.
WebAssembly gives you: a sandbox with no ambient authority, sub-millisecond instantiation, memory measured in kilobytes per instance, near-native execution, and a compilation target for a dozen languages.
what the component model adds#
Core WebAssembly can only pass integers and floats across its boundary. Everything else — strings, structs, lists, results — requires a hand-written serialization convention on both sides. Every host invented its own and none of them interoperated.
The component model defines a real interface type system, described in WIT (WebAssembly Interface Types):
package readme:plugin@1.0.0;
interface transform {
record document {
title: string,
body: string,
tags: list<string>,
}
variant error {
parse-failed(string),
unsupported,
}
process: func(input: document) -> result<document, error>;
}A component written in Rust exports that interface. A host written in Go imports it. Neither knows about the other's language. The types are checked at composition time.
That is the missing piece. It turns WebAssembly from "a fast sandbox you have to build a protocol on top of" into "a plugin system."
the capability model#
A component gets nothing by default. No filesystem, no network, no clock, no random numbers, no environment variables. Every capability is explicitly granted by the host, and can be granted narrowly — this one directory, this one host, read-only.
That is a genuinely different security posture from every mainstream plugin system, and it is the right one. The failure mode of "a plugin can do anything the process can do" has produced a very long history of incidents.
WASI provides the standard interfaces for the capabilities a host chooses to grant, so components are portable across hosts that grant the same things.
where this is actually being used#
- Edge compute platforms, where cold start time is the product and containers are too slow.
- Database extensions, where you want user-defined functions without letting them segfault the database.
- Proxy and gateway filters, where the same filter should run in several different proxies.
- Plugin systems in developer tools, where users want to write extensions in their own language.
the honest state of it#
Good: the core specification is stable, the toolchains for Rust and C are mature, the runtime implementations are production-quality.
Mixed: language support varies enormously. Rust and C are excellent. Go works. Anything with a garbage collector and a large runtime — Python, Ruby, the JVM — produces large binaries and slower startup, though the WasmGC work improves this substantially for languages that adopt it.
Still rough: debugging across the component boundary, async and streaming interfaces, and the tooling story for anyone who is not writing Rust.
the recommendation#
If you are building anything extensible — an editor, a data pipeline, a platform, a game — evaluate this before you design your own plugin API. The security model alone justifies it, and the language-agnostic interface means your plugin ecosystem is not limited to people who like your language.
If you are not building anything extensible, this is not for you, and the browser-performance story is much less interesting than the marketing suggested in 2017.
— Dom, January 24, 2026