How We Built a Serverless Notebook with WebAssembly and Rust
A deep dive into architecting an interactive, serverless computational notebook using Rust compiled to WebAssembly, edge functions, and persistent block storage.
How We Built a Serverless Notebook with WebAssembly and Rust
Interactive notebooks are powerful: they combine code, documentation, and results. Traditional notebook platforms rely on long-lived servers to provide runtime capabilities. In this post I’ll describe how our team built a serverless notebook that runs compute in the browser and at the edge using Rust compiled to WebAssembly. The result is a fast, secure, and scalable notebook experience that integrates with Programa.Space's edge functions and persistent block storage.
Design goals
Before implementation we defined goals:
- Security: No arbitrary code execution on multi-tenant backend servers.
- Performance: Low-latency execution for typical data-transform tasks.
- Scalability: Many simultaneous short-lived executions without maintaining heavy servers.
- Reproducibility: Deterministic containerized builds and cached artifacts.
Why Rust + WASM?
Rust offers memory safety and zero-cost abstractions. Compiled to WebAssembly, Rust code runs inside sandboxed runtimes that are supported across modern browsers and edge platforms. This model satisfies our security and performance goals: compute runs close to users, constrained by deterministic sandbox limits.
System architecture
High level components:
- Client UI: Single-page app (Svelte) that hosts the notebook editor and result panes.
- WASM execution environment: Two modes — in-browser runtime for quick iterations; edge runtime for heavier operations and shared data access.
- Storage: Object store for larger artifacts and a block-storage layer for snapshots.
- Control plane: A lightweight control API running as serverless functions that orchestrates snapshotting, dependency resolution, and access control.
Sandboxing and resource limits
Resource constraints are crucial. For the edge runtime, we used the platform’s configurable sandbox that imposes CPU and memory quotas and wall-clock timeouts. We instrumented the runtime to emit metrics for execution time and resource usage. On the client we limit WASM memory and disable certain modules that may access low-level APIs.
Dependency management
Cells may declare small crates from a curated registry. To keep builds fast and deterministic we:
- Use a curated index of precompiled crates compiled to WASM with specified feature flags.
- Cache compiled WASM modules in the object store keyed by content-addressed hashes.
- Allow users to bring their own crates via signed manifests after administrative review.
Execution flow
When a user runs a cell:
- The client compiles small snippets via the in-browser WASM toolchain where possible, or dispatches a build job to the edge builder when heavy dependencies are needed.
- If the compiled artifact exists in the cache, the edge runtime pulls it and executes the code in a sandboxed WASM instance.
- Outputs are serialized as JSON or binary blobs and persisted to the object store with a short-lifetime URL for display.
Persistence and sharing
Notebooks are stored as versioned documents with snapshots that capture the exact compiled artifacts referenced by the notebook. This ensures that a shared notebook can reconstruct the environment and reproduce results. Snapshots are small when using precompiled artifacts and grow only when users embed large outputs.
Performance tradeoffs
WASM provides predictable performance but carries startup overhead for cold modules. To mitigate this, we maintain a warm cache for popular crates and pre-initialize runtime pools at the edge. For CPU-bound operations like numeric kernels, Rust + SIMD optimizations in WASM help close the gap with native speeds.
Developer experience
We built an SDK to make it easy to author notebook kernels in Rust. The SDK includes:
- Helper macros for input/output serialization.
- Utilities for chunked streaming of results to reduce memory spikes.
- Debugging helpers that instrument and export lightweight traces to the control plane.
Security review process
To allow users to bring external crates, we added an administrative review workflow. Crates are scanned for known supply-chain issues and required to adhere to the sandboxed interface. Malicious or unsafe patterns are blocked.
Lessons learned
- Start with a curated dependency set — allowing anything increases costs and risk.
- Balance client- vs edge-execution based on latency and resource needs.
- Focus on reproducibility — users expect a notebook to behave the same tomorrow.
Conclusion
Building a serverless notebook on top of Rust + WASM enables a secure and performant experience that scales with the number of users. By combining in-browser execution for fast iteration with edge execution for heavier workloads and curated artifacts for reproducibility, we delivered a notebook that feels both modern and practical. If you’re interested in trying the SDK or contributing to the crate index, check our repository on Programa.Space and join the community discussion.
Related Topics
Ethan Zhou
Systems Engineer
Senior editor and content strategist. Writing about technology, design, and the future of digital media. Follow along for deep dives into the industry's moving parts.