Skip to main content
← Back

Event Sourcing with the Wasm Component Model & Resources

The August 13, 2025 wasmCloud community call is a deep conversation on the Wasm component model applied to event sourcing. Brooks Townsend walks through an experimental repo that models an entire event-sourcing system purely from the composability of WebAssembly components — command handlers, event handlers, an event sourcer, and an event store — using Wasm resources as opaque handles so the core system can pass commands and events around as bytes without knowing their structure. Yordis Prieto then shares his multi-year journey from Elixir event sourcing into WebAssembly, why he chases Wasm to control indeterminism, and the concrete WIT features (maps, structs, recursive types, generics) he is pushing for upstream — including a recent conversation with Luke Wagner.

Key Takeaways

  • Event sourcing maps cleanly onto components: Brooks' POC represents the whole pattern — command handlers, event handlers, the event sourcer, and the event store — as separate WebAssembly components composed together, so a developer only writes domain logic while the system handles routing and storage transparently
  • Wasm resources shine as opaque handles: an owned resource (much like a file descriptor) lets commands and events cross the component boundary as opaque handles; the core works with bytes and only serializes/deserializes to concrete types at the edges, which Brooks called the cleverest part of the design
  • You don't have to use WIT for serialization: Brooks generated his event and command types from protobuf definitions to show the serialization format is the developer's choice, and to get an event-catalog-style site of how events relate "for free"
  • Yordis chases Wasm to control indeterminism: after years of Elixir event sourcing, he wants the platform — not developer discipline — to remove the clock and other sources of nondeterminism, so engineers can write deterministic domain logic in any language
  • The ideal experience is "three data structures and two functions": state, command, and events, plus an evolve/apply function and a command handler — with all of wasmCloud and WebAssembly invisible underneath
  • WIT needs richer data types: Yordis is pushing for native maps/dictionaries, structs (JSON-like values), and recursive types, plus generics, to close the gap so a WIT specification could replace separate protobuf definitions
  • Luke Wagner is engaged: Yordis met with Luke (a wasm and WASI P3 designer) who is already working on a maps specification; structs and recursive types are trickier and likely come later
  • Concrete use cases drive the spec: Brooks emphasized that a real "here's how I want to write this app" example is exactly what helps shape what the component model and WIT should look like next

Chapters

Meeting Notes

Brooks' Event Sourcing POC: Modeling a System in WIT

Brooks opened with an experimental repo that asks a single question: can you represent an entire event-sourcing system using only the composability of WebAssembly components? He was careful to frame it as a thought exercise rather than production software — event sourcing is an opinionated space, and the goal was to handle all the plumbing (where commands and events go, how they get stored, how they route to handlers) transparently so a developer only authors domain logic.

The model is expressed in WIT, which Brooks described as essentially a description of an application's functionality. He defined a handful of interfaces: a command handler (what he had previously called an aggregate) that receives a command — like "record transaction" or "open account" — and returns a list of events such as "account opened" or "account open failed"; an event handler that reacts to events entering the system and can return commands in response; the event sourcer component that routes a command to the right command handler and queries for events; and a persistent storage layer (the event store) that records each emitted event with a timestamp as an immutable fact.

Resources as Opaque Handles, and Protobuf for Events

The cleverest part, Brooks argued, was the use of Wasm resources. An owned resource behaves like a file descriptor: when you pass it around it is just an opaque handle. That lets the core system work with events and commands without knowing their concrete structure — every command, event, and state can be serialized to and deserialized from a list of bytes, so the whole system passes bytes around efficiently and only materializes concrete types at the edges. To represent the actual event types, Brooks did something deliberately "wacky" and generated them from protobuf definitions, for two reasons: to demonstrate that you are not required to use WIT for serialization (you could use JSON or anything else), and because tools like event-catalog can turn proto/OpenAPI event definitions into a generated site showing how events and commands relate — "dope to just have for free." His sample command handler implemented just two functions: a rehydrate (fold every past event into current state) and a handler that, for a bank transaction, checks the account balance and emits either a denial or a success.

Yordis' Journey: Elixir, Determinism, and Why WebAssembly

Yordis traced a roughly five-year path through event sourcing, starting professionally around 2020 in Elixir with the commanded framework. He distilled the pattern to its essentials: a few data structures (state, command, events, and value objects) and exactly two computational functions — an evolve/apply (given a state machine and an event, return the new state — the function Brooks called rehydrate) and a command handler (given a state machine and a command, produce events or an error). Having built a full US banking system, he achieved correctness by allowing no indeterministic code — everything was assertions on messages — which required telling developers, by discipline, never to call clocks or anything nondeterministic.

That reliance on discipline is what pushed him to WebAssembly. As he put it, if the platform never hands the guest a clock, the guest cannot misuse it: "if I don't give you the clock, you don't get to use the clock." WebAssembly lets him remove indeterminism at the platform level rather than trusting every developer, and it lets engineers use Go, JavaScript, or whatever language they prefer while he still controls the runtime. That combination — controlling the platform, controlling side effects, and staying polyglot — is what led him to wasmCloud, which he sees as the layer that takes these components, injects the right dependencies at the right time, and manages the infrastructure (including NATS for messaging) underneath.

Crossing the Wasm Boundary and the WIT Wishlist

Both speakers converged on the core challenge: how to represent a command, an event, and a state so they can cross the WebAssembly boundary in a concrete, developer-provided way. Brooks noted that Yordis' use of Extism is the classic WASI P1 answer — when you can't represent a concrete type, you fall back to a Vec<u8> and pointers, exactly what wasmCloud did years ago — but the component model now provides a rich language for describing complex types, and resources come close to expressing generics. The drawback remains that whenever a resource must be stored or deserialized into a concrete type, you still cross from bytes to type.

Yordis' wishlist for WIT, which he raised in a recent conversation with Luke Wagner (a creator of Wasm and a designer of WASI P3 and the component model), centers on three things: native maps/dictionaries (he doesn't want to manually convert lists of tuples to maps everywhere), structs (JSON-like, arbitrarily nested values), and recursive types — plus generics, so a single WIT file could be templated across data types instead of repeating evolve/handle definitions per command. His motivation is alignment: he wants to avoid building a bloated SDK on top of WIT that fragments the ecosystem ("I don't want to be creating soup culture"), and ideally to close the gap so a WIT specification could serve as the data-type spec instead of maintaining protobuf separately. Brooks reported Luke agrees on maps and is already working on a specification; structs and recursive types are trickier (recursion in particular), and likely follow. The pair closed on the principle that concrete use cases — "here is how I want to write an application that targets Wasm" — are exactly what drive the implementation forward, even if some answers end up being "document the trade-off and move on."

WebAssembly News and Updates

This call doubled as a status check on what the Wasm component model can and can't yet express. The headline is the live, upstream push to enrich WIT: native maps/dictionaries are being specified (with Luke Wagner actively working on it), while structs (JSON-like recursive values) and recursive types are recognized as harder follow-on work. The broader theme is that the component model's resources already get surprisingly close to representing generics and opaque, typed handles across the guest/host boundary — enough to model an entire event-sourcing system today — while the community continues filling in the missing data-type primitives one at a time. For developers tracking the WebAssembly System Interface, the related WASI Preview 3 work on native async, streams, and futures is the other major spec frontier. Follow the Bytecode Alliance and the component model repo for ongoing updates.

What is wasmCloud?

wasmCloud is a CNCF project that lets you build applications using WebAssembly components and deploy them anywhere — cloud, edge, or Kubernetes clusters. It uses the WebAssembly component model to let you write business logic in any supported language (Rust, Go, Python, TypeScript, C#, and more) while the platform handles capabilities like HTTP, messaging, and key-value storage through a pluggable provider architecture. As this call shows, that same composability is exactly what makes patterns like event sourcing tractable: you express domain logic as components, define their contracts in WIT, and let the platform inject the right dependencies and manage the infrastructure. With built-in OpenTelemetry observability and Kubernetes integration, wasmCloud bridges WebAssembly's portable, sandboxed execution model and production cloud-native infrastructure.

Topic Deep Dive: The Wasm Component Model

Every thread in this meeting traces back to the Wasm component model. Event sourcing works as a set of composed components precisely because the component model provides typed interfaces and resources — owned, opaque handles that let a command or event cross the boundary without the core system trusting or even understanding its internals. That same machinery is why Brooks could swap in protobuf-generated types without WIT having to know about them, and why resources "are actually almost close to representing something like generics." The current limits are equally instructive: the component model has no native generics, no maps, no structs, and no recursive types yet, which is exactly the gap Yordis is working to close upstream. As those primitives land in WIT, more real-world patterns — event sourcing among them — become expressible directly in the component model without falling back to byte-array workarounds. wasmCloud's bet is that the component model becomes the universal contract for composing portable, sandboxed business logic across languages.

Who Should Watch This

This call is especially valuable for developers building event-driven or event-sourcing systems who want to see how the pattern maps onto WebAssembly components and resources (start with Brooks' POC at 3:11), language and framework authors weighing how to represent domain types across the Wasm boundary and what WIT can and can't yet express (Yordis' deep dive from 12:26), and anyone following the component model and WIT roadmap who wants concrete, use-case-driven context on maps, structs, recursive types, and generics (the Luke Wagner discussion at 43:59).

Up Next

The community continues to feature builders showing real applications of WebAssembly. Brooks shared a link to Yordis' event-sourcing reference PR as an interesting pattern for others to explore, and Yordis committed to sharing links to the upstream issues around the WIT features he is pushing — native maps/dictionaries, structs, and recursive types. With wasmCloud about halfway through its quarter, expect a roadmap check-in on an upcoming call, and more community demos of what people are building.

Get Involved

wasmCloud is a CNCF project and contributions are welcome. Join the community:

Full Transcript

Read the complete transcript with speaker labels and timestamps:

Read the full transcript →