AL+

Language: RO (română) EN (English)

Email us: paul@alplustech.com

Looking back at the week of 12–18 February 2025

A Wasm plugin needs a small contract before a runtime

Go's WASI reactors made callable extensions practical. Define their data, memory and capability contracts before choosing a runtime for your application.

Citiți articolul în română

A plugin becomes maintainable when the host can state what it accepts, what it returns and what it may access. Choosing WebAssembly does not settle those questions. A runtime can execute the module while the application still lacks a stable contract for data, errors and resource use.

Looking back from November 2026, Go's February 2025 reactor support is useful because it makes this boundary explicit. The Go 1.24 announcement, dated 11 February, establishes the release. The 13 February explanation describes exported Go functions and WASI reactors whose exports remain callable after initialization. Those features enable an extension mechanism; the host still owns its design.

The business consequence appears when a plugin changes independently of the main application. A small, versioned interface lets the owner reason about compatibility. An extension allowed to depend on undocumented application internals can turn every host release into a coordinated migration of all plugins.

Initialization is part of the contract

The dated Go explanation shows go:wasmexport and a reactor built for GOOS=wasip1, GOARCH=wasm with -buildmode=c-shared. The host calls _initialize before exported functions; main is not automatically invoked. This is February 2025 behavior described by that post, not an assertion that every later Wasm target behaves identically.

That lifecycle matters beyond startup syntax. A reactor instance can retain state between calls. The host should decide whether an instance belongs to one request, one customer or a longer-lived worker. Reusing it without a stated rule can let cached values or partially completed operations affect later work.

Consider an illustrative extension that calculates an order adjustment. It receives only the fields needed for that calculation and returns a proposed adjustment with an explanation code. It cannot itself commit the order. This is a proposed boundary, not an implementation or experiment conducted for this article.

The example keeps a business decision in the host: whether to accept and record the adjustment. It also makes retry behavior easier to describe. Repeating a calculation has different consequences from repeating a plugin call that already charged a payment method or sent a message.

The ABI is smaller than the domain model

An application binary interface, or ABI, describes how the host and module exchange calls and values. The Go post demonstrates a small numeric export. It does not establish that arbitrary Go objects can be passed freely across the boundary. Design the interface against the supported types and target behavior rather than extrapolating from familiar in-process function calls.

For richer payloads, an illustrative design could exchange serialized data through an explicitly managed buffer. Specify encoding, maximum size, allocation ownership and when memory can be released. A pointer and length are meaningful only if both sides agree which memory they refer to and how long the contents remain valid.

Define errors separately from successful business results. A rejected adjustment, malformed input and a runtime trap require different responses. If every failure becomes an empty result, an operator cannot tell whether the plugin made a legitimate decision or failed before making one.

Version the data contract before independent authors rely on it. State how unknown fields and unsupported versions are handled. Keeping a small stable envelope can be more valuable than exposing the application's full internal order structure, which may change for reasons unrelated to extensions.

Capabilities are decisions made by the host

A module's useful authority comes from the interfaces and resources the host makes available. For the illustrative calculation, supplying the required order fields may be enough. Giving it general file or network access because a library expects those facilities broadens the contract and the work needed to assess it.

Decide each capability from the product requirement. If the extension needs a reference value, the host might provide that value as input instead of offering unrestricted access to a database. That can reduce hidden dependencies and make the calculation easier to reproduce. It is a design option, not a universal performance or security guarantee.

The host also needs limits on work and a response to exceeded limits. Memory growth, execution time, cancellation and output volume require explicit policies supported by the chosen runtime. Check the actual runtime and version before relying on a particular control; this historical Go announcement does not certify those controls.

Wasm should therefore never be described as universal sandbox safety. Runtime defects, overly broad host imports, sensitive inputs and flawed authorization can all matter. A narrow capability contract reduces the authority deliberately granted to a plugin, while the full security assessment remains specific to the deployment.

A process can be the more honest boundary

The strongest counterargument is an extension that needs unrestricted native dependencies, its own operating-system behavior or a substantial existing service stack. Forcing that workload into a small Wasm interface can create adapters more complicated than the business function itself.

A separate process or service may then express the requirement more clearly. It brings operational responsibilities for startup, communication, authentication and failure handling. It also has its own security configuration. The point is to compare explicit costs and capabilities, rather than treating either a process or a Wasm module as automatically safe.

Choose the boundary before selecting a runtime. Write one representative request and response, the permitted side effects and the behavior on timeout or invalid output. A proposed acceptance exercise would review those cases with both host and plugin owners. No runtime comparison or application build was performed for this article.

In custom software development, the valuable deliverable is a contract the next maintainer can explain. Start with the smallest extension that solves a real product need. Keep authority in the host where practical, and move to a process when the dependencies genuinely require a broader environment.