
POWERED BY WASM
WASM.IO 2025
Daniel Vigovszky

INTRODUCTION

INTRODUCTION
Golem is a serverless durable execution platform

INTRODUCTION
Golem is a serverless durable execution platform
Server-side WebAssembly applications

INTRODUCTION
Server-side WebAssembly applications
Why WASM?
Examples
What can we contribute?
Golem is a serverless durable execution platform

INTRODUCTION
Before Golem

INTRODUCTION
Before Golem
zio-flow
JVM based
Scala DSL
Durable execution

WASM CORE


WASM CORE

Sandbox
Performance
Language support



WASM CORE

Sandbox
Performance
Language support



WASM CORE

Sandbox
Performance
Language support
Growing support
No lock-in



WASM CORE

Sandbox
Performance
Language support
Safety
Transparent durability



oplog (journal)
automatic snapshots
custom snapshots



WASM CORE




Full control of outside world
Deterministic
Restore app state by recording everything non-deterministic

WASM CORE




Example

WASM CORE




/// Updates the component's state by adding a random value to the total.
fn add() {
STATE.with_borrow_mut(|state| {
let value = rand::rng().next_u64();
state.total += value;
println!("The new total is {}", state.total);
});
}
/// Returns the current total.
fn get() -> u64 {
STATE.with_borrow(|state| state.total)
}
WASM CORE




(import "wasi_snapshot_preview1" "random_get" (func ...))
(import "wasi_snapshot_preview1" "fd_write" (func ...))
(import "wasi_snapshot_preview1" "environ_get" (func ...))
(import "wasi_snapshot_preview1" "environ_sizes_get" (func ..))
(import "wasi_snapshot_preview1" "proc_exit" (func ..))
Simplified oplog:
- exported function called: 'add'
- imported function 'random_get' returned 1234
- exported function called: 'add'
- imported function 'random_get' returned 4567
- exported function called: 'get'
Contains much more information in reality

WASM CORE




To recover the application state, we just replay this log
Simplified oplog:
- exported function called: 'add'
- imported function 'random_get' returned 1234
- exported function called: 'add'
- imported function 'random_get' returned 4567
- exported function called: 'get'
Replay loop: 'add', 'add', 'get'
Host function implementation returning the stored response

WASM CORE




async fn get_random_u64(&mut self) -> anyhow::Result<u64> {
let durability = Durability::<u64, SerializableError>::new(
self,
"golem random",
"get_random_u64",
DurableFunctionType::ReadLocal,
)
.await?;
if durability.is_live() {
let result = Host::get_random_u64(&mut self.as_wasi_view()).await;
durability.persist(self, (), result).await
} else {
durability.replay(self).await
}
}
WASM CORE




Cannot recover to a specific arbitrary instruction
But this does not matter
Not good for CPU intensive applications
Good enough for many use cases

WASM CORE




Full snapshot of the program
Linear memories
Tables
File system
Resource states
Prototype
On the roadmap

WASM CORE




Custom snapshotting
interface save-snapshot {
save: func() -> list<u8>;
}
interface load-snapshot {
load: func(bytes: list<u8>) -> result<_, string>;
}

WASM CORE




Custom snapshotting
Compact
Allows arbitrary updates
Requires contribution from the user
Updates
Soon:
recovery optimization

WASM CORE




Restoring a running program is a core feature

Not always needed

Durable workers
Ephemeral workers
Stateless, fast, short lived, single call
Long running
Multiple invocations
Stateful

WASM CORE






Idle workers can be dropped from memory
Between invocations
When waiting

WASM CORE






Special trap
Triggered by wasi:io/poll
if let Some(Some(deadline)) = all_supports_suspend {
let duration = deadline.duration_since(Instant::now());
if duration >= self.ctx().suspend_threshold {
return Err((self.ctx().suspend_signal)(duration));
}
}
Suspend signal
Drop
Schedule recovery

COMPONENT MODEL

COMPONENT MODEL
Golem is built on the Component Model
Impl in wasmtime starts ~ May, 2022
Golem starts ~ Apr, 2023
(using wasmtime 8.0.0)
Enables many features
Trying to not reinvent the wheel

COMPONENT MODEL
Golem is built on the Component Model
Golem workers = WASM component instances

COMPONENT MODEL
Invocation
Expose a typed API from our workers
Multiple invocations
Multiple exposed functions
Golem invocation API
WASM Component exports
=


COMPONENT MODEL
Invocation
Golem invocation API
WASM Component exports
=
package wasmio:example1;
interface api {
add: func(value: u64);
get: func() -> u64;
}
world wasmio-example1 {
export api;
}
Component name: wasmio:example1
Component version: 0
Component size: 1.93 MiB
Created at: 2025-03-04 19:17:52.625270002 UTC
Exports:
wasmio:example1-exports/api.{add}(value: u64)
wasmio:example1-exports/api.{get}() -> u64


COMPONENT MODEL
Invocation
Component name: wasmio:example1
Component version: 0
Component size: 1.93 MiB
Created at: 2025-03-04 19:17:52.625270002 UTC
Exports:
wasmio:example1-exports/api.{add}(value: u64)
wasmio:example1-exports/api.{get}() -> u64
How do we extract this?
golem-wasm-ast crate
wit-parser

planned migration

COMPONENT MODEL
COMPOSITION

Golem runs multiple components
Exposes their exports
Components can be composed
Worker to Worker Invocations
Component
Composition
=

COMPONENT MODEL
COMPOSITION

Worker to Worker Invocations
Component
Composition
=
Same behavior
Architectural decision

COMPONENT MODEL
RPC

golem-wasm-rpc crate
wRPC
first version ~February 2024
planning to migrate
Let's see how Golem's WASM RPC works!

COMPONENT MODEL
RPC

wasm-rpc host interface
stub generator

COMPONENT MODEL
RPC

wasm-rpc host interface
stub generator
resource wasm-rpc {
constructor(target: worker-id);
ephemeral: static func(target: component-id) -> wasm-rpc;
invoke-and-await: func(
function-name: string,
function-params: list<wit-value>) -> result<wit-value, rpc-error>;
// .. async version
// .. scheduled version
}

COMPONENT MODEL
RPC

wasm-rpc host interface
stub generator
record wit-value {
nodes: list<wit-node>,
}
variant wit-node {
record-value(list<node-index>),
variant-value(tuple<u32, option<node-index>>),
enum-value(u32),
flags-value(list<bool>),
tuple-value(list<node-index>),
list-value(list<node-index>),
option-value(option<node-index>),
result-value(result<option<node-index>, option<node-index>>),
prim-u8(u8),
// ...
handle(tuple<uri, u64>)
}
COMPONENT MODEL
RPC

wasm-rpc host interface
stub generator
Implemented by Golem
Any Golem component can import it
Invoke another workers
Hard to use (constructing wit-value)
Not type safe

COMPONENT MODEL
RPC

wasm-rpc host interface
stub generator
worker A
worker B

COMPONENT MODEL
RPC

worker A
worker B
package example:counter;
interface api {
inc-by: func(value: u64);
get: func() -> u64;
}
world counter {
export api;
}
package example:caller;
world caller {
export test: func() -> u64;
}

COMPONENT MODEL
RPC

worker A
worker B
package example:counter;
interface api {
inc-by: func(value: u64);
get: func() -> u64;
}
world counter {
export api;
}
package example:caller;
world caller {
import example:counter/api;
export test: func() -> u64;
}
Regular function call
Let Golem solve it
Which worker?

COMPONENT MODEL
RPC

worker A
worker B
package example:counter;
interface api {
inc-by: func(value: u64);
get: func() -> u64;
}
world counter {
export api;
}
package example:caller;
world caller {
import example:counters/api;
export test: func() -> u64;
}
Which worker?
package ex:counter-client;
interface counter-client {
resource counter {
constructor(t: worker-id);
inc-by: func(value: u64);
get: func() -> u64;
}
}
world counter-client {
export api;
}

COMPONENT MODEL
RPC

Generated stub WIT
Generate implementation
Rust
Compile to WASM
Compose with caller
Mark the stub interface names in metadata
Dynamic linking
DEPRECATED
Inspired by wRPC

COMPONENT MODEL

Dynamic linking
Instantiating the component
Missing imports
Check if they are marked as RPC stubs
Link with host function directly calling the RPC implementation

COMPONENT MODEL

Dynamic linking
Generic idea

COMPONENT MODEL

Dynamic linking
Generic idea
OpenAPI client
gRPC client
Smithy client
GraphQL client




COMPONENT MODEL

Dynamic linking
Generic idea



Generate a client WIT from some spec
Generate a composable client component
or
Directly support via dynamic linking

COMPONENT MODEL

Dynamic linking
Generic idea



Typed configurations


COMPONENT MODEL

Dynamic linking
Generic idea



Typed configurations
Specify a set of configuration properties
Generate a WIT interface
Dynamic linking provides the actual configuration values


COMPONENT MODEL





Invocation semantics
Invocations are processed
sequentially
limitation
feature


COMPONENT MODEL





Invocation semantics
limitation
feature
WASI P3


COMPONENT MODEL





Invocation semantics
WASI P3
user choice
Worker to Worker Invocations
Component
Composition
=
Sync/async components
Interleaving external invocations


COMPONENT MODEL





Persistent sockets
WASI P3



Client 1
Client 2

websocket
Golem worker

API gateway

COMPONENT MODEL





Persistent sockets
WASI P3



Client 1
Client 2

websocket
Golem worker

Connected client: remote resource
API gateway
RPC
Streaming interface

COMPONENT MODEL





Persistent sockets
WASI P3


Connected client: remote resource
Streaming interface
REQUIREMENTS

COMPONENT MODEL





Persistent sockets
WASI P3


Connected client: remote resource
Streaming interface
RPC with first-class resource support
WASI P3 streams
Interleaved invocations
REQUIREMENTS

COMPONENT MODEL





PERMISSION MODEL


Another use case for resources, composition and wRPC
How to constrain worker-to-worker communication?


COMPONENT MODEL





PERMISSION MODEL


Another use case for resources, composition and wRPC

Resources as permits
Derive more strict ones
Root permit associated with the worker
RPC calls require permit
Permits can be shared via RPC

COMPONENT MODEL





PERMISSION MODEL


Another use case for resources, composition and wRPC

Generalize this further

COMPONENT MODEL





PERMISSION MODEL


Another use case for resources, composition and wRPC

Make WASM RPC the primary protocol
to manipulate Golem itself
using the same permission model

COMPONENT MODEL





PERMISSION MODEL



Make WASM RPC the primary protocol
Golem services become "fake" WASM RPC instances
Side effect
Evolve non-Golem specific tooling / libraries

COMPONENT MODEL





COMPOSITION (2)



Composition exposed to users


COMPONENT MODEL





COMPOSITION (2)



Composition exposed to users
Plugins


COMPONENT MODEL





COMPOSITION (2)



Composition exposed to users
Plugins

oplog processor plugins
component transformer plugins
library plugins

COMPONENT MODEL





COMPOSITION (2)



Composition exposed to users
Plugins

oplog processor plugins
component transformer plugins
library plugins
Dynamically re-compose your Golem app

COMPONENT MODEL





COMPOSABLE DURABILITY




Implement durability as a composable WASI wrapper
(instead of wrapping the host functions in the executor)
FAILED

COMPONENT MODEL





COMPOSABLE DURABILITY





poll
poll
User component
Golem executor
Durable WASI
poll
poll

COMPONENT MODEL





COMPOSABLE DURABILITY





poll
poll
User component
Golem executor
Durable WASI
poll
poll
package golem:wasi;
world durable-wasi {
// ...
import wasi:io/poll@0.2.0;
export wasi:io/poll@0.2.0;
// ...
// Golem durability API
import golem:durability/durability@1.2.0;
}
COMPONENT MODEL





COMPOSABLE DURABILITY





poll
poll
User component
Golem executor
Durable WASI
poll
poll
The composed component uses the wrapped WASI implementations

COMPONENT MODEL





COMPOSABLE DURABILITY





poll
poll
User component
Golem executor
Durable WASI
poll
poll
RPC stub
Generated RPC client
RPC stub
RPC
RPC

COMPONENT MODEL





COMPOSABLE DURABILITY





poll
poll
User component
Golem executor
Durable WASI
poll
poll
RPC stub
Generated RPC client
RPC stub
RPC
RPC
resource future-invoke-result {
subscribe: func() -> pollable;
get: func() -> option<result<wit-value, rpc-error>>;
}
COMPONENT MODEL





COMPOSABLE DURABILITY





poll
poll
User component
Golem executor
Durable WASI
poll
poll
RPC stub
Generated RPC client
RPC stub
RPC
RPC
RPC
RPC
FIXED!

COMPONENT MODEL





COMPOSABLE DURABILITY





poll
poll
User component
Golem executor
Durable WASI
poll
poll
RPC stub
RPC
RPC
RPC
FIXED?
Dynamic RPC linking

COMPONENT MODEL





COMPOSABLE DURABILITY




Can't create the wrapped pollable in the dynamic linked host function
Workaround?
Poll was just an example
FAILED

COMPONENT MODEL





DURABILITY API




package golem:durability@1.2.0;
interface durability {
// ...
current-durable-execution-state: func() -> durable-execution-state;
persist-typed-durable-function-invocation: func(
function-name: string,
request: value-and-type,
response: value-and-type,
function-type: durable-function-type,
);
read-persisted-durable-function-invocation: func() ->
persisted-durable-function-invocation;
// ...
}

WASI


WASI

Golem should run "any" program

WASI

Golem should run "any" program
No custom host API

WASI

Golem should run "any" program
No custom host API
if there is a WASI interface for it

WASI

Interfaces provided by Golem
Everything wasmtime-wasi has
wasi:cli, wasi:clocks, wasi:filesystem, wasi:http, wasi:io, wasi:random, wasi:sockets
Additional storage interfaces
wasi:blobstore, wasi:keyvalue
Logging
wasi:logging
Relational database access
golem:rdbms
Golem specificÂ
golem:api, golem:durability, golem:rpc

WHAT CAN WE CONTRIBUTE?

WHAT CAN WE CONTRIBUTE?
Rib
App manifest
WIT
Rust crates
JS/TS/Scala.js






WHAT CAN WE CONTRIBUTE?
Rib

Scripting language to work with Golem components

WHAT CAN WE CONTRIBUTE?
Rib

Scripting language to work with Golem components
Primarily for describing APIs

WHAT CAN WE CONTRIBUTE?
Rib

- method: Post
path: "/{user-id}/add-item"
binding:
response: |
let quantity: f64 = request.body.quantity;
let product_id: u64 = request.body.product-id;
let name: string = request.body.name;
let price: f64 = request.body.price;
let input = {product-id: product_id, name: name, price: price, quantity: quantity};
let worker = instance("shopping-cart-${request.path.user_id}");
worker.add-item(input);
{status: 200u64, body: success}API gateway
HTTP request/response
Worker invocation

WHAT CAN WE CONTRIBUTE?
Rib

let quantity: f64 = request.body.quantity;
let product_id: u64 = request.body.product-id;
let name: string = request.body.name;
let price: f64 = request.body.price;
let input = {product-id: product_id, name: name, price: price, quantity: quantity};
let worker = instance("shopping-cart-${request.path.user_id}");
worker.add-item(input);
{status: 200u64, body: success}
Calling WASM components
Access context

WHAT CAN WE CONTRIBUTE?
Rib

Statically typed with type inference
Types are component model types
Value syntax is WAVE
Pattern matching
List comprehensions and reduce
String interpolation
First-class worker and resource support
WIT package/interface inference
let res: result<str, str> = ok("foo");
match res {
ok(v) => v,
err(msg) => msg
}
let x = foo("abc");
match x {
bar({a: _, b: _}) => "success",
foo(some_list) => some_list[0]
} let x = ["foo", "bar"];
for p in x {
yield p;
}
let ages: list<u16> = [1, 2, 3];
reduce z, a in ages from 0 {
yield z + a;
}let worker = instance("my-worker");
let cart = worker.cart("bar");
cart.add-item({
product-id: a,
name: b,
quantity: c,
price: d}
);
cart.remove-item(a);
cart.update-item-quantity(a, 2);
let result = cart.get-cart-contents();let worker1 = instance();
let result1 = worker1.qux("bar");
let worker2 = instance();
let result2 =
worker2.qux[amazon:shopping-cart]("bar");
let worker3 =
instance[amazon:shopping-cart]();
let result3 = worker.qux("bar")

WHAT CAN WE CONTRIBUTE?
Rib

No need to only use for API mappings!
Testing
Rib REPL to interact with workers

WHAT CAN WE CONTRIBUTE?
Rib

Not Golem specific!
Scripting language for WASM components
Scripting language for wRPC
or

WHAT CAN WE CONTRIBUTE?
Rib

Rust crate implementing type checking / compilation / execution
Planned to be published completely separated from Golem

WHAT CAN WE CONTRIBUTE?


App Manifest
A yaml file

WHAT CAN WE CONTRIBUTE?


App Manifest
A yaml file
Describing one or more Golem components

WHAT CAN WE CONTRIBUTE?


App Manifest
A yaml file
Describing one or more Golem components
Relationships (for example RPC)

WHAT CAN WE CONTRIBUTE?


App Manifest
A yaml file
Describing one or more Golem components
Relationships (for example RPC)
Build and compose components
Fully customizable, and built-in templates for:






WHAT CAN WE CONTRIBUTE?


App Manifest
Build tool that understands...
WIT directories
Stub generation
Composing components

WHAT CAN WE CONTRIBUTE?


App Manifest
Example

WHAT CAN WE CONTRIBUTE?


App Manifest
golem app new demo rust
cd demo
golem component new rust demo:rust-component
golem component new ts demo:ts-component
golem component new moonbit demo:moonbit-component
WHAT CAN WE CONTRIBUTE?


App Manifest


WHAT CAN WE CONTRIBUTE?


App Manifest

Assembles wit/deps directories
cargo component build
componentize-js
moon build
wasm-tools component ...
Caching and up-to-date checks

WHAT CAN WE CONTRIBUTE?


App Manifest
components:
demo:rust-component:
template: rust
demo:ts-component:
template: ts
demo:moonbit-component:
template: moonbit
dependencies:
demo:rust-component: []
demo:ts-component:
- type: static-wasm-rpc
target: demo:rust-component
demo:moonbit-component:
- type: wasm-rpc
target: demo:ts-component

WHAT CAN WE CONTRIBUTE?


App Manifest


WHAT CAN WE CONTRIBUTE?


App Manifest

Generate stub WITs
Auto-import stubs into components
Generates and build static stubs
Compose components when needed

WHAT CAN WE CONTRIBUTE?


App Manifest
Golem specific at the moment..
but it does not have to be!
Could be a glue for guest-language tooling

WHAT CAN WE CONTRIBUTE?


WIT

We want to build on standard interfaces
but sometimes we cannot wait

WHAT CAN WE CONTRIBUTE?


WIT

golem:rdbms

WHAT CAN WE CONTRIBUTE?


WIT

golem:rdbms
WIT package for working with PostgreSQL and MySQL
Not Golem specific
Implemented in Golem, ready to try out

WHAT CAN WE CONTRIBUTE?

Would be happy to cooperate to make it one of the standard interfaces
WIT

golem:rdbms


WHAT CAN WE CONTRIBUTE?


crates


Golem itself is open-source

WHAT CAN WE CONTRIBUTE?


crates


Golem itself is open-source
Some core libraries can be useful for non-Golem use cases

WHAT CAN WE CONTRIBUTE?


crates


Golem itself is open-source
Some core libraries can be useful for non-Golem use cases
golem-wasm-astgolem-wasm-rpcgolem-rib+ app manifest shared library?
higher level component model AST
various component model "Value" encodings
the scripting language

WHAT CAN WE CONTRIBUTE?




JS/TS/Scala.js

JS/TS support is very important for Golem

WHAT CAN WE CONTRIBUTE?




JS/TS/Scala.js

JS/TS support is very important for Golem
Testing heavily the ecosystem - jco/componetnize-js/StarlingMonkey/...
Reporting issues
Pull requests with fixes

WHAT CAN WE CONTRIBUTE?




JS/TS/Scala.js

We love Scala

WHAT CAN WE CONTRIBUTE?




JS/TS/Scala.js

We love Scala
Scala.js WASM component model support is WIP
until then..
wit-bindgen-scalajs
+ sbt plugin
+ Golem app manifest template

WHAT CAN WE CONTRIBUTE?





Scala.js can be used to create WASM components right now!

FINAL THOUGHTS

FINAL THOUGHTS
Better support for WIT evolution
Code-first WIT tooling
Dynamic linking for JS/PY components (?)
Snapshotting support in wasmtime
wishlist


FINAL THOUGHTS
Better support for WIT evolution
wishlist
SemVer support in wasmtime
SemVer support in other places
Data evolution?
new variant case
new optional record fields

FINAL THOUGHTS
wishlist
Code-first WIT tooling
Spec (WIT) first
Alternative: code first
Native component model support
Language-specific libraries (macros, etc)
Goal: users do not have to learn WIT

FINAL THOUGHTS
wishlist
Dynamic linking for JS/PY components
WASM generated with componentize-js and componentize-py are huge
Native image caching helps
Can the JS/Py engines be separated from the user code?

FINAL THOUGHTS
wishlist
Snapshotting support in wasmtime

Serialize the state of an instance and ability to restore it
Prototype works (but only snapshots memory)
What about function tables?
Host-owned resources?
Snapshot during execution
Snapshot during execution


THANK YOU
Daniel Vigovszky
Golem Cloud - Powered By WebAssembly
By Daniel Vigovszky