Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Open Source Summit North America 2026: Building...

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

Open Source Summit North America 2026: Building a Shared, Persistent Virtual Filesystem for WebAssembly

Avatar for ternbusty

ternbusty

May 16, 2026

More Decks by ternbusty

Other Decks in Programming

Transcript

  1. Building a Shared, Persistent Virtual Filesystem for WebAssembly Ayako Hayasaka

    Software Engineer, LY Corporation Open Source Summit NA 2026
  2. About Me • Ayako Hayasaka • Software engineer, LY Corporation

    in Japan ◦ Web backend engineering • Personal OSS project ◦ kontainer-runtime: low-level container runtime written in Kotlin/Native ◦ MonakaFS: host-independent virtual filesystem for WebAssembly @ternbusty
  3. Agenda 1. WebAssembly basics 2. Why do we need a

    virtual filesystem for WebAssembly? 3. Three different approaches a. Build-time composition (wac plug) b. Host-trait implementation (shared in-process) c. RPC dynamic attachment (cross-process) 4. Introducing persistence using S3 5. Performance evaluation 6. Which approach to choose?
  4. What is WebAssembly (Wasm)? A binary instruction format for a

    stack-based virtual machine originally designed for browsers Source Code wasm module (.wasm binary) Build Load & Instantiation Wasm Runtime Instance Linear Memory You write code in Rust, C, Go, etc. and compile to Wasm Accesses only isolated linear memory (sandboxed environment) A .wasm binary is called a "module"
  5. Limitations of Wasm Modules Low-level Interfaces Only No standard way

    to pass strings, structs, or complex data Imports/exports can only pass numbers (i32, i64, f32, f64) Hard to Compose Two modules in different languages can't easily talk to each other Every project invents its own glue code and serialization Memory Safety One module can corrupt another’s memory Modules share linear memory and read/write to each other's memory directly
  6. The Component Model WIT (Wasm Interface Type) • The interface

    definition language • Rich types: strings, lists, ... • Components can import and export WIT interfaces exports Component B (originally written in Rust) Component A (originally written in C) I need this interface I provide this interface imports Component C Composition • wac plug: Plug exports into imports, produce a new component
  7. The Component Model Memory Safety • Each component has its

    own isolated linear memory and passes data through WIT interface • Canonical ABI: lifting / lowering copies data across boundaries Load & Instantiation Wasm Runtime Instance A Linear Memory Instance B Linear Memory
  8. Wasm Beyond the Browser • Now expanding to server-side, edge

    computing, IoT, and more • Why use Wasm outside the browser? ◦ Lightweight & fast: microsecond-order cold starts ▪ Frameworks like Fermyon Spin appeared ◦ Sandboxed: memory isolation from the host (linear memory) ◦ Portable: same binary runs anywhere a Wasm runtime exists
  9. WASI: Accessing Host Resources • WebAssembly itself has no I/O,

    it's pure computation • WASI (WebAssembly System Interface) bridges that gap ◦ Preview 1 (stable), Preview 2 (2024, Component Model based) • Filesystem access via preopen: ◦ Host grants access to specific directories ◦ Wasm app directly uses the host's filesystem
  10. Problems with preopen • Security risks: Weakens the Wasm sandbox

    model ◦ CVE-2023-51661: runtime bug allowed unauthorized host FS access ◦ The whole point of Wasm sandboxing is lost if apps touch host files • Portability issues: ◦ Path separator differences (Windows vs Unix) ◦ Environment-dependent behavior breaks "write once, run anywhere" We need a virtual filesystem independent of the host filesystem!
  11. Existing Solutions and Their Limitations Description WASI Read Write Persis

    tence Multi-app Sharing Note wasi-vfs A virtual filesystem layer for WASI Preview 1 o x x x Hard to use from languages like Rust because of wasi- libc dependency wasi-virt Virtualization Component Generator for WASI Preview 2 by Bytecode Alliance Preview 2 o x x x Neither meets all of our requirements
  12. Existing Solutions and Their Limitations Description WASI Read Write Persist

    ence Multi-app Sharing WasmFs emscripten’s VFS - (Browser Only) o o o x wasmer virtual-fs VFS for wasmer (wasm runtime) Not Standard (WASIX) o o x x Cloudflare Workers /tmp per request Preview 1 o o x x Fermyon Spin VFS is not provided, host mount or use of KV Store are recommended Fastly Compute No filesystem access, use of KV store is recommended Platform / Runtime dependent solutions are also limited
  13. Our Goals Build a host-independent Virtual File System (VFS) for

    WebAssembly: 1. Logical isolation from host OS filesystem ◦ No preopen, no host FS dependencies 2. Existing apps work without modification ◦ Applications can use standard I/O such as fopen or std::fs 3. Flexible deployment options ◦ Build-time composition, multi-app sharing, RPC, S3 persistence
  14. File System Access Using WASI Source Code std::fs::read("test.txt") wasm module

    (.wasm binary) Build (target=wasip2) import section code section Wasm Runtime Load & Instantiation Instance wasi:filesystem Code that calls the wasi:filesystem interface wasi:filesystem implementation import is resolved Call host‘s syscalls inside App’s filesystem call is resolved to be a call to the host’s filesystem
  15. File System Access Using WASI Source Code std::fs::read("test.txt") wasm module

    (.wasm binary) Build (target=wasip2) import section code section Wasm Runtime Load & Instantiation Instance wasi:filesystem Code that calls the wasi:filesystem interface wasi:filesystem implementation import is resolved Call host‘s syscalls inside By providing a custom implementation that satisfies the wasi:filesystem interface definition, filesystem calls are directed to our implementation instead of the host's. Replacing the FS Implementation
  16. Approach 1: Build-Time Composition exports wasi:filesystem VFS Adapter Wasm Runtime

    App VFS Adapter the actual filesystem data imports wasi:filesystem App Load & Instantiation Linear Memory composed into a single wasm binary wasi-virt-like architecture
  17. Approach 1: Build-Time Composition VFS Adapter export wasi:filesystem WIT Definition

    Source Code implements WIT definition and converts FS calls to fs-core call Dependent Library fs-core core logic of in-memory file system function call App Source Code std::fs::read("test.txt") Provide in-memory VFS function such as Inode management, block assignment Build (target=wasip2) Build (target=wasip2)
  18. app component import section wasi:filesystem adapter component export section wasi:filesystem

    code section wasi:filesystem implementation code section code to call wasi:filesystem data section embedded directory directory Can embed a directory (if you want to read the directory content when the app starts) wac plug (into a single wasm binary) wasm component app component adapter component No wasi:filesystem import nor export
  19. Approach 1: Use Cases & Limitations • Use Cases ◦

    Bundle config files into the binary ▪ Embed directories at build time via CLI ◦ Temporary working area ▪ Image processing pipeline, etc. • Limitations ◦ No persistence, data lost on exit ◦ Cannot share FS between multiple apps What if we need multi-app sharing?
  20. Approach 2: Host Trait Implementation Wasm Runtime App App the

    actual filesystem data imports wasi:filesystem App wasi:filesystem implementation is provided from host Runner VFS Host wasi:filesystem implementation Load Overview When Running… The actual filesystem data is in the host memory (not linear memory) and can be shared with multiple apps within the same process Link VFS Host as a wasi:filesystem implementation App
  21. Approach 2: Host Trait Implementation Runner (Written in Rust) Source

    Code • Load & instantiate wasm app • Link VFS Host as wasi:filesystem implementation Dependent Library wasmtime VFS Host (Rust Library) Source Code Implement wasi:filesystem host trait and convert it to fs-core call Dependent Library fs-core dependent Build Native binary app component app component Load Load Introduced RwLock for concurrent access from multiple Wasm instances because host runs multiple instances on separate threads and concurrent FS access is possible
  22. Approach 2: Use Cases & Limitations • Use Cases ◦

    Edge device data pipelines ▪ Sensor -> temp file -> processing module ◦ Cache server (Fermyon Spin style) ▪ Per-request Wasm instances share FS ▪ FS as cross-request cache • Limitations ◦ No persistence, data lost on exit ◦ Must distribute a native binary ◦ Limited to sharing within one host process What about cross- process sharing?
  23. Approach 3: RPC Dynamic Attachment RPC Adapter App RPC Adapter

    App VFS RPC Server the actual filesystem data Linear Memory Wasm Runtime App RPC Adapter Wasm Runtime App RPC Adapter Wasm Runtime VFS RPC Server communicate via RPC Apps and filesystem run in different runtime processes and communicate via RPC
  24. Approach 3: RPC Dynamic Attachment RPC Adapter export wasi:filesystem WIT

    Definition Source Code implements WIT definition and converts FS calls via RPC VFS RPC Server Source Code Convert RPC calls to fs-core calls Dependent Library fs-core app component wac plug (into a single wasm binary) VFS RPC Server Wasm Runtime App RPC Adapter communicate via RPC Accepts file operation requests over TCP sockets using Protocol Buffers
  25. Approach 3: Use Cases & Limitations • Use Cases ◦

    CI/CD build cache sharing across pipeline stages ◦ Dynamic scaling: new workers connect to existing FS ◦ Processes with different lifecycles sharing data • Limitations ◦ Network latency on every FS operation ◦ No persistence, data lost on exit How can we add persistence?
  26. Adding persistence using S3 • Problem: all 3 approaches are

    in-memory, data lost on exit • Solution: sync the VFS with Amazon S3-compatible storage ◦ Similar concept to s3fs-fuse on Linux ◦ But no FUSE, no root privileges, no kernel dependencies ◦ Works on any platform • Can be added to any of the 3 approaches: ◦ Build-Time Composition: add to VFS Adapter ◦ Host-trait implementation: add to VFS Host ◦ RPC dynamic attachment: add to VFS RPC Server
  27. S3 Sync Strategies • Read path: ◦ Read-through: every read

    hits S3 ◦ Memory-cache: serve reads from memory • Write path: ◦ Write-through: upload on every write ◦ Async: queue writes, upload in background • Background sync: ◦ Cold-start restore: load S3 state on startup ◦ ETag-based polling: detect remote changes
  28. Eval 1: Build-Time Composition vs Host Filesystems (Throughput for 100MB

    file size) 2143 3160 1743 0 2000 4000 Build-Time Composition tmpfs (in memory) ext4 (disk) 1459 3883 796 0 2000 4000 Sequential Read (MB/s) Sequential Write (MB/s) IO Performance: tmpfs > Build-Time Composition (proposed) > ext4 Build Time Composition achieved over 1GB/s throughput 1483 2025 27 0 2000 4000 Random Read (MB/s)
  29. Eval 2: Comparing the Three Approaches (Throughput for 100MB file

    size) Sequential Read (MB/s) Sequential Write (MB/s) Random Read (MB/s) Host Trait Implementation achieved the best performance The performance of RPC was limited especially in random read 1893 9730 875 0 2500 5000 750010000 Build-Time Composition Host Trait RPC 1165 1665 29 0 1000 2000 1593 3903 750 0 2000 4000
  30. Eval 3: S3 Sync Performance (Latency for 1MB File Size)

    Sequential Read Latency (msec) Sequential Write Latency (msec) IO performance: Host Trait ≒ s3fs-fuse > Build-Time > RPC 93.3 216.3 124.8 221 0 50 100 150 200 250 s3fs-fuse (for comparison) Build-Time Composition Host Trait RPC 225.4 290.9 183.6 281 0 100 200 300 400
  31. Comparison & Selection Guide Build-Time Host-Trait RPC I/O Performance Good

    Best Slow Portability Best (single .wasm binary) Good (must distribute native binary ) Good (Server should be started up beforehand) Data Sharing None (without S3, no sharing) Same Process Cross Process S3 Sync Yes Yes Yes Use Case Examples Config bundling / temporary files Multi-app in the same process Dynamic workers whose lifetime differ (like CI/CD) Users can select the best method based on their use case
  32. Limitations & Future Work (1) • Memory constraints: ◦ In-memory

    FS bounded by host RAM ◦ Build-Time Composition & RPC: 4GiB linear memory limit (memory64 will help) • RPC performance: ◦ Caching / prefetching to reduce round-trips
  33. Limitations & Future Work (2) • Distributed locking for S3

    ◦ Current: single-writer consistent ◦ Multi-writer needs a distributed lock manager • Large file streaming ◦ Direct S3 streaming without loading into memory
  34. Summary • We built a host-independent virtual filesystem for WebAssembly

    ◦ Improves security for cloud providers ◦ Provides portable file operations for app developers • Three approaches + S3 persistence: ◦ Build-time composition: portable, self-contained ◦ Host-trait implementation: best performance, in-process sharing ◦ RPC dynamic attachment: cross-process, dynamic scaling • Open source: https://github.com/ternbusty/monaka-fs • Thank you! Questions?