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-ast
golem-wasm-rpc
golem-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

Private

Golem Cloud - Powered By WebAssembly