Skip to content

Component Model vs Core Modules

Flow-Like auto-detects whether a .wasm binary is a WebAssembly Component Model component or a core module. It adapts the binary’s ABI and exposes both as the same Flow-Like node abstraction.

Component Model and core-module binaries using different ABI layers before converging on one Flow-Like capability and resource boundary

Component ModelCore module
InterfaceWIT interfacesRaw WebAssembly exports
Data exchangeCanonical ABI generated from WITJSON through linear memory
Export namesget-node, get-nodes, run, get-abi-versionget_node, get_nodes, run, optional get_abi_version
Memory handoffGenerated by component bindingsPacked pointer/length values; module alloc and dealloc are optional helpers
Direct TCP / UDP / DNSAvailable through WASI networking when a network capability enables itNot exposed
HTTPWASI HTTP and Flow-Like host bridge, subject to capabilitiesFlow-Like host bridge where the template SDK implements it
Format detectionComponent headerFalls back to core-module loading
Flow-Like resultNode definitions and WasmExecutionResultThe same

The repository’s WIT world is flow-like:[email protected]. It imports Flow-Like interfaces for logging, pins, variables, cache, streaming, metadata, storage, models, authentication, HTTP, schemas, images, database operations, and WebSockets.

The component exports node definitions and execution results as strings containing JSON. Language bindings handle the canonical ABI representation, so package code does not manually pack pointers and lengths.

The runtime crate and Rust SDK currently declare numeric ABI version 2, while several other maintained SDKs still emit 1. The loader records the reported value but does not currently reject a binary solely because the number differs. Use the value supplied by the language template rather than hard-coding the Rust value. The numeric ABI is separate from the WIT package version.

The component linker provides WASI Preview 2 and WASI HTTP interfaces. Flow-Like host functions check their corresponding capabilities. The component linker enables TCP, UDP, and DNS lookup separately when their capabilities are granted; the explicit allow_wasi_network override enables all three. Socket address checks also apply the execution configuration’s host allowlist and block server-side destinations covered by the execution environment’s egress policy. The desktop loader for installed packages copies the manifest’s allowed_hosts into the node’s execution configuration; the server executor does not. The Flow-Like HTTP host function does not consult the list, so enforce destination restrictions at the executor or network-policy layer.

An enabled network category is not blanket filesystem or process access.

A core module exports:

ExportContract
get_node()Returns a packed pointer and length for one JSON definition
get_nodes()Returns a packed pointer and length for a JSON definition array
run(ptr, len)Reads execution-input JSON and returns result JSON
alloc(size)Optional module allocator
dealloc(ptr, size)Optional module deallocator
get_abi_version()Optional numeric ABI version

At least one of get_node or get_nodes is required. When alloc is absent, the host uses its bounded allocator.

Core modules call flat Flow-Like host functions. They do not receive direct WASI socket access; network-capable core templates use the Flow-Like HTTP host bridge when their SDK supports it.

The maintained formats are:

Component ModelToolchain
Rustwasm32-wasip2 and wit-bindgen
GoTinyGo and generated WIT bindings
C++wasi-sdk, wit-bindgen-c, and component wrapping
ZigZig, generated C bindings, and component wrapping
C#.NET WASI tooling
SwiftSwiftWasm, generated C bindings, and component wrapping
Pythoncomponentize-py
TypeScriptcomponentize-js
Core moduleToolchain
AssemblyScriptasc
KotlinKotlin/Wasm with runtime GC and exception features enabled
NimEmscripten backend
LuaEmbedded Lua runtime compiled with Emscripten
JavaTeaVM
GrainNative WASM output
MoonBitNative WASM output

The binary format does not guarantee identical SDK coverage. Check templates/wasm-capability-matrix.md before depending on a host function in a particular language.

NeedChoice
New package and a maintained Component Model template existsPrefer the Component Model
Direct TCP, UDP, or DNS accessComponent Model, with explicit permissions
Existing compatible core-module packageKeep the core module unless migration has a clear benefit
Language only has a maintained core templateCore module
Small computation-only nodeEither; choose the better-supported template

Do not wrap a core module as a component only to change the file header. A real migration requires WIT bindings and the component export contract.

Both formats:

  • run in Wasmtime;
  • are cached by content and can use precompiled artifacts;
  • receive node-specific capability configuration;
  • are bounded by fuel, epoch interruption, memory, and timeout controls;
  • produce the same node definitions, outputs, execution-pin activations, and error shape.

The ABI layer differs; the permission boundary and Flow-Like workflow model do not.

Upgrade the runtime and precompiled artifacts

Section titled “Upgrade the runtime and precompiled artifacts”

Build the API, compilation workers, and executors with the same Wasmtime major version. The workspace currently pins Wasmtime 48.0.1; use the repository’s host Rust toolchain for those components. A worker rejects jobs whose target key names another Wasmtime version, so a version 48 worker cannot publish artifacts under a wt47 key.

Precompiled .cwasm artifacts from Wasmtime 47 cannot run on Wasmtime 48. Registry and local cache platform keys derive their version from the workspace dependency. Current keys include linux-x86_64-wt48 and ios-pulley64-wt48. Source .wasm packages retain their node ABI and do not need to be rebuilt for this runtime upgrade.

When deploying the upgrade:

  1. Coordinate the API, compiler, and executor rollout. If EXECUTOR_PLATFORM is configured outside the repository, change its suffix to wt48 while retaining the executor’s operating system and architecture.
  2. Request Linux artifacts for active packages with POST /admin/packages/ensure-wasm-artifacts. Use the registry’s package recompilation operation for other required targets.
  3. Wait for the required targets to finish compiling before routing runs to upgraded executors. The API requires the current target’s artifacts before dispatching a package.

Local caches discard incompatible artifacts and compile source Wasm again when compilation is enabled. Executors can fall back to verified source Wasm when a downloaded artifact cannot be deserialized. Deployments with compilation disabled need matching wt48 artifacts in advance.

Wasmtime 48 denies TCP and UDP socket creation by default. The protocol grants described above enable permitted sockets; the HTTP host interfaces retain their separate capability checks. Upstream details are in the 48.0.0 release notes and 48.0.1 fixes.

  1. Copy flow-like-node.wit into the package’s WIT source.
  2. Generate bindings using the destination language template.
  3. Implement the WIT exports instead of raw pointer/length exports.
  4. Replace flat host calls with generated interface calls.
  5. Build a real component and run the template’s interoperability tests.
  6. Publish it as a new package version and re-check all declared permissions.