> The promise of wasi components has not been fulfilled. The market wants to hotload and link artifacts dynamically. The wasi project requires insider wizardry to use it that way: the offering has been statically linking components before you ship. Defeating 99% of the use cases.

I think both of these points on the spectrum (on the one end, fully static linking of WASI components within a monolithic single-source project; and on the other end, dynamic-at-runtime compiling + linking + loading + "hot instantiating" of arbitrary black-box WASI-component artifacts, with dynamic [presumably reflection-based?] API discovery to drive interaction with those components) are strawmen. There are relatively few "real" use-cases for WASI on either of these ends.

Most of the stuff anyone is really interested in using WASI for (AFAICT, from the use-cases for it I've seen in the wild) involves something closer to the midpoint between these two points. Somewhat dynamic and modular, but with no JIT compilation / components-fetching-components / hot component instantiation / dynamic reflection stuff going on.

Specifically, the "point" of WASI (in my opinion, and in the opinion of most people I've spoken with about it), is to serve as a sort of meta-standard (with tooling) for concrete "pluggable runtime" systems to implement plugin-support SDKs in terms of.

In such "plugin ecosystems", every "plugin" (WASI component) is of the same shape (i.e. exposing the same endpoints, and expecting the same capabilities.) And so the host runtime, and each of its plugins, can be precompiled (separately, in separate projects!) against that shape. And the plugin host can load arbitrary wasm components into a pre-baked plugin "slot" at runtime, because there's no dynamism / introspection / reflection / component framework support required or involved. The plugin host isn't a component itself; it's just ordinary host runtime code, written once. The component framework doesn't load the component; the host runtime does. Etc.

In a sense, this is "custom binding" as you were talking about. But it's custom binding against a WASI-specced target; which is what enables different plugins to be runtime-fungible within the same plugin "slot" from the host's perspective. (While giving you sandboxing for free, unlike the traditional "a plugin is just a DLL that exports certain symbols" approach.) WASI does all the work plugin hosts want of it at component compile/link time: verifying that the plugin is of the expected ABI shape, and guaranteeing sandboxing (by a WASI component inherently being a thing developed to run as an isolate under an abstract machine.) The fact that a compiled+linked WASI-component artifact is a blob of WebAssembly built against certain WIT interfaces, isn't just something tagged onto it by external metadata; it's also something inherent to the structure of the resulting artifact, i.e. a property determinable via static analysis.

At runtime — or slightly earlier, at plugin "install" time — a plugin host might not even keep the component as a component. It might preprocess it into a DLL, or whatever its runtime's equivalent of a DLL is. (A Java class file, say.) The crucial thing was that the component was a component when it was handed off from the downstream developer to the plugin host. Because then any code generated to wrap the component into a host-runtime-native module, is code trusted by the host, rather than code controlled by the downstream developer.

---

If your goal is to compile some one-off blob of WebAssembly code into an artifact that you can then e.g. treat like an old-school ActiveX component from browser JavaScript, then yeah, you don't need WASI at all for that. You're not trying to create a plugin ecosystem. You don't need to spec out a standard "socket" for downstream devs to plug into. You're just "plugging X into a thing that expects only and exactly X". So skip WASI; just use a one-off custom binding. (Though I would note that the WASI work has acted as a forcing function for the WebAssembly-component ABI, enabling you to write much richer custom bindings than you would have been able to write before WASI.)

But if you're:

- developing a FaaS runtime like Cloudflare Workers

- developing a game engine that allows "mods"

- developing a cloud-hosted agent sandbox, where the toplevel is code (that invokes LLMs, that invoke capabilities)

- developing a modern replacement for Wordpress, with an aim to allow just as much extensibility but to not repeat Wordpress's endless vulnerabilities

(etc)

...or, in other words, if you are developing an application or service that O(N) downstream-developed things (workloads, plugins, mods, extensions, whatever you want to call them) all plug into; where you want these things to all plug into your host system in a very precise and controlled way, rather than being given free rein to touch anything they want; and where these interaction patterns can all be described in one of a few very specific shapes, with a precisely definable spec for 1. what API the runtime wants to call into on the component; and 2. what APIs the runtime wants to hand to the component, to enable the component to call those APIs...

...then WASI was developed precisely for you.

And, more specifically, WASI was created so that you could:

1. use WASI to define that API spec (as machine-readable WIT files); and then

2. give that spec, and those WIT files, to the developers in your ecosystem;

3. so that they could then use existing WebAssembly+WASI tooling to build WebAssembly components that target your API spec. (Most likely not by expecting them to independently bootstrap a WebAssembly+WASI dev environment; but rather, by you shipping an SDK that embeds WebAssembly+WASI tooling and your WIT files together.)

(I would also note that this — i.e. "the thing WASI solves for" — is actually a rather rare use-case on the whole. Your average dev isn't [and shouldn't be!] building an ecosystem for API-sandboxed plugins of their code. The few devs that do need to construct their own plugin ecosystems around their project, probably can therefore be expected to go quite deep on learning any required "insider wizardry." If that was even required. Which it generally isn't, when all you're trying to do is to load one of N unknown-until-runtime but statically-defined-ABI-shape plugin components; rather than trying to load arbitrary runtime-generated dynamically-defined-ABI-shape components, allowing those components to load or compile+exec further components, etc.)