Skip to main content
← Back

wasmCloud 2.11: Wasm Runtime Autoscaling at 42,000 Workloads per Core, and TypeScript via Perry

The October 21, 2026 wasmCloud community call came the day after the wasmCloud 2.11 release, which turns its policy enforcement points to deny by default. Victor Adossi showed that a single pinned CPU core and a 512 MiB memory budget now hold 4,000 warm or 42,000 scale-to-zero HTTP components. These numbers are the kind of evidence that wasm runtime autoscaling depends on. He then demonstrated JCO running TypeScript compiled to a kilobyte-sized WebAssembly component by Perry, with no JavaScript engine inside.

Key Takeaways​

  • wasmCloud 2.11 enforces by default. The policy enforcement points added over the last few releases move from count mode to enforce and deny by default. You can set them back to count mode. The release blog covers the changes and how to upgrade
  • A threat model is in review. PR #5685 adds a short THREAT_MODEL.md that says what is in and out of scope for a wasmCloud vulnerability and which boundaries the host defends. A Security Insights file (#5724) builds on it for the CNCF Security Slam badges
  • Security Slam cleanup. Bailey Hayes is retiring repos that predate wasmCloud 1.0 (#5692), updating CNCF governance metadata, and checking dependency licenses with cargo-deny. Each license outside the CNCF allowlist, such as MPL-2.0, now has its own exception request
  • One core holds 4,000 warm components. With 2.11's performance fixes, a host pinned to one CPU with a 512 MiB process-memory budget served 4,000 warm wasi:http P3 components at 0.5 ms p50 and 0.8 ms p99, up from about 2,600. Each warm workload cost about 70 KiB
  • And 42,000 scale-to-zero components. Per-workload cost for scale-to-zero fell from about 197 KiB to 11.9 KiB, so the same budget held 42,000 on one core and 42,500 on two, at 1.2 ms p50 and 1.9 ms p99 including the cold start. A host density benchmark (#5708) lets you reproduce it. Victor asked for results from other hardware
  • Macs no longer freeze under load. New memory limits, detection, and dynamic checks stop the host from launching components when memory runs low. Without them, macOS lets a process use all memory and lock up the machine
  • TypeScript without a JavaScript engine. JCO now tests components built by Perry, which compiles TypeScript through LLVM to a WASI P2 component measured in kilobytes. A StarlingMonkey-based ComponentizeJS component typically starts at about 7 MB and ends up around 10 MB. Perry's WASI support isn't released yet, and it can't yet bind arbitrary WIT interfaces

Chapters​

Meeting Notes​

wasmCloud 2.11: Deny by Default​

Bailey Hayes opened with KubeCon two weeks away and a large release cut the day before. She merged the wasmCloud 2.11 release blog live on the call. wasmCloud publishes a release blog for each minor release to curate what landed and give upgrade tips, because the raw changelog isn't readable. Bailey said Eric Gregory and Victor Adossi landed more changes than she did this cycle. She also thanked regular contributor Junjie, Betty Blocks for long-running bug reports and fixes, and a new contributor whose pattern for preventing panics when acquiring permits she extended to the other kinds of permits in the system.

The main change is that the policy enforcement points introduced over the last few releases, which ran in count mode, now enforce and deny by default. Anyone who needs to relax them can switch back to count mode. These are the controls previewed on the October 14 call for guest memory, socket egress, and hostPath volumes.

Threat Model and the Security Slam​

One of the Q4 roadmap items is a threat model. PR #5685 adds a short THREAT_MODEL.md that says what is in scope and out of scope for a wasmCloud vulnerability, which boundaries the host protects, and how to relax enforcement. Its diagram puts the operator and control plane and the host process (Wasmtime, wash-runtime, and native plugins) on the trusted side, and workloads and their clients on the untrusted side.

Bailey registered wasmCloud for the fall CNCF Security Slam, which ends just before KubeCon. Its PRs include a cleanup that archives repos from before wasmCloud 1.0, updates to the new CNCF metadata formats (maintainer lists are now YAML rather than Markdown), and a cargo-deny license check. The check files a CNCF exception for each dependency license outside the allowlist, such as MPL-2.0. Next is a Security Insights file (#5724) that builds on the threat model and records the practices from wasmCloud's Q2 security CI sprint: attestations and signing, SBOMs, CodeQL, cargo audit, Go vet, Dependabot, and zizmor on every GitHub Actions workflow. The Security Insights file is required for one of the early badges. Victor asked in chat whether that meant security was done. Bailey answered that it never will be, but the posture will be strong and well documented.

Density: How Many Components Fit on One Core​

Victor Adossi presented the scale work behind many of 2.11's perf and fix PRs. Density has long been part of WebAssembly's pitch: a machine runs tens of VMs and hundreds of containers (Kubernetes also limits pods per node), while Wasm workloads pack far tighter inside one process. Some fixes were for macOS, which lets a process use all available memory and freezes the machine because there is no OOM killer to step in. The host now detects this, has a switch to set max memory with more reasonable defaults, and checks memory as it goes. It backs off and refuses to launch components rather than crashing.

To keep results consistent, Victor pinned the host to one or two CPU cores with a 512 MiB process-memory budget and ran a basic wasi:http P3 component built in Rust. On one core, 4,000 warm components stayed loaded, up from about 2,600, at 0.5 ms p50 and 0.8 ms p99 for local requests. The limit is now the instance pool: four core instances per workload times 13,106 slots is 4,368, and raising --core-instances is the next step. Scale-to-zero reached 42,000 components on one core and 42,500 on two, because per-workload cost fell from about 197 KiB to 11.9 KiB. Those requests include waking a scaled-to-zero component and took 1.2 ms p50 and 1.9 ms p99. Starts were two to five times faster, and CPU time per start fell from about 1.5 to 1.9 ms to 0.2 to 0.6 ms. Victor noted that P2 is still slightly faster than P3. He thinks there may be another order of magnitude available.

Frank Schaffa asked about response times when all 4,000 are serving HTTP. The p50 and p99 figures above answer that for local traffic. Victor asked people to run the new host density benchmark (#5708). It adds bench-scale, which drives a host over the NATS host API, and a scale_density bench in wash-runtime, and it prints a results table. He wants numbers from other machines, including Apple M5s and big servers. Bailey planned to merge it that day (it has since merged) and run it on the project's bench host, a tuned AMD Ryzen machine with the CPU governor set to performance.

Benchmark Shapes and the Comparisons That Matter​

Frank asked whether the runs would show the cost of OpenTelemetry. Bailey said Jeremy Fleitz's k6 work is the place for OTel comparisons. She explained the shapes of wasmCloud's benchmarks: density tests are new; k6 means end to end, close to running against a real cluster; and Criterion and Gungraun are micro-benchmarks that count instructions and catch excess allocations. Asked what to compare against, Victor suggested a plain Rust server such as Axum or Tower on the same number of CPUs. Jeremy described his work comparing a scratch Go container autoscaled with KEDA against tuned Rust components in wasmCloud on Kubernetes, with OTel on and off.

Liam Randall pointed out that these are not like-for-like comparisons. MicroVM platforms such as E2B claim about 900 microVMs on the largest hardware, but each still needs around 512 MB of memory. Those platforms isolate at the virtual-machine layer, so per-process and per-invocation isolation still needs other tools, such as seccomp for system calls, eBPF for the network, and Landlock or Bubblewrap for processes. wasmCloud's sandbox isolates in process, in resources (for example against thundering herds), and in time, and adds policy enforcement for files, network, secrets, and config. He mentioned having crashed his Mac at about 500,000 workloads, in an unrelated test, before Victor's guardrails landed. He suggested a hackathon to see whether one host can run a million. Bailey said all of this work is open in the wasmCloud repo. AI has been very effective for security analysis and fuzzing (every AI-driven campaign she runs turns up one or two issues to patch), and Liam, Victor, and Jeremy have been using it for performance testing and tuning.

TypeScript Components Without an Engine: Perry and JCO​

Victor then turned to JCO. Most JavaScript-to-WebAssembly work embeds an engine such as QuickJS or StarlingMonkey. A newer approach compiles ahead of time. Porffor compiles JavaScript to C, which WASI SDK can turn into a component, and it now has a WASI build. Perry starts from TypeScript, parses and type-checks it with SWC, and compiles through LLVM IR to native code on many platforms (including GTK desktop apps) or to WebAssembly. Perry's experimental --target wasi produces a WASI P2 component, and its docs already anticipate P3.

Victor added a Perry backend to JCO and a perry-filesystem example. The guest is ordinary TypeScript that calls readFileSync and statSync from node:fs. Perry compiles those calls to WASI P2 filesystem imports, and jco transpile runs the result in Node.js or the browser. JCO will test the example against every release. For now it needs a custom Perry build, because Perry hasn't released its WASI support. The result is an engineless component measured in kilobytes. A ComponentizeJS component built on StarlingMonkey starts at about 7 MB and typically ends up around 10 MB, and a Rust component is usually hundreds of kilobytes. Because Perry reuses SWC, TypeScript support should be solid, apart from edge cases in the newest features of the Go-based TypeScript compiler.

Liam asked about the Node.js support Victor recently added to JCO. You can turn that support on or off in jco transpile, so Node built-ins can be implemented by the host or compiled into the guest by Perry, which ships its own Node implementation in Rust. Victor wants to measure the difference, and do the same for StarlingMonkey's emerging Node support.

What Perry Needs, and What Could Come Next​

The missing piece is arbitrary WIT interfaces. ComponentizeJS uses an "embedding splicer" that turns a WIT interface into C++ glue attached to the component. Perry has no equivalent, so a Perry program can't import an arbitrary WIT interface yet. A wit-bindgen generator for Perry is next, and Victor called it "a prompt away." The other gap is web built-ins: Perry focuses on Node.js built-ins, and Victor hasn't checked its WinterTC or fetch coverage. Bailey's proposed roadmap: Perry support in wit-bindgen, then Perry as an option or the default in the wasmCloud TypeScript SDK, then density tests that compare off-the-shelf StarlingMonkey and QuickJS components with Perry. That fits the "Are we componentized yet?" goal of giving people the data to choose.

Victor described the trade-off. Many engine instances are heavy, many Perry components are light, and one pooled engine running many small scripts could be lighter still, with less isolation. Bailey floated compiling Perry itself into a host component so that users ship scripts and get small scheduled workloads. Victor said that is possible, since LLVM has a Wasm build, but other work should come first. Bailey sees a gap for a TypeScript-first runtime with Bun and Deno "getting slurped up," and Liam noted that this approach delivers isolates done in Wasm.

To close, Bailey asked people to book KubeCon and said she hopes to bring at least an outline of the wasmCloud KubeCon workshop to the next call for community feedback on topics and missing docs. Aditya Salunkhe asked in chat whether Perry would open up the Node.js ecosystem. Victor said yes for packages that depend only on Node's APIs rather than native C++ addons, and that Node ecosystem support can already be tried through the JCO host today.

WebAssembly News and Updates​

In webassembly news this week, JavaScript and TypeScript are getting ahead-of-time compilers for WebAssembly. Perry compiles TypeScript through LLVM to WASI P2 components, Porffor compiles JavaScript to C, and the Bytecode Alliance's JCO can now build and test Perry components alongside its StarlingMonkey-based ComponentizeJS path. On the supply-chain side, the CNCF's fall Security Slam is pushing projects toward threat models, Security Insights files, and per-dependency license exceptions. For the component model, the new density numbers are a reminder of what WASI and Wasmtime make possible: tens of thousands of isolated wasi:http handlers in one process.

What is wasmCloud?​

wasmCloud is a CNCF project for building applications out of WebAssembly components and running them across cloud, edge, and Kubernetes clusters. The Wasm component model lets you write business logic in Rust, Go, Python, TypeScript, C#, Java, and more. The platform supplies capabilities like HTTP, messaging, key-value storage, blob storage, and observability through standard interfaces and a pluggable host plugin architecture backed by Wasmtime. wash is the developer shell for building, running, deploying, and debugging. The runtime operator schedules Wasm workloads on Kubernetes the same way you schedule containers, with WASI Preview 3 support on by default. Together they give you a production platform for WebAssembly on Kubernetes and at the edge.

Topic Deep Dive: What Density Means for Wasm Runtime Autoscaling​

Wasm runtime autoscaling depends on two costs: what an idle workload costs while it waits, and how long it takes to wake one. The 2.11 numbers measure both. A scale-to-zero workload costs about 11.9 KiB of host memory, so 42,000 of them fit in a 512 MiB budget on one core. Waking one and serving its request took 1.2 ms at p50 and 1.9 ms at p99, which includes the cold start. Warm workloads cost about 70 KiB each, and on one core the limit is the instance pool, not memory. Compare that with a container or microVM, where an idle replica still costs tens to hundreds of megabytes and a cold start takes seconds. With Wasm, scaling to zero is the normal case.

These are local, single-host numbers from one benchmark, and Victor was explicit that more data is needed: other CPUs and architectures, OTel on and off, and end-to-end runs through Kubernetes and KEDA from Jeremy Fleitz's k6 suite. The host density benchmark makes that possible. Run bench-scale against your own host and contribute the table. For the deployment side, see workloads and components, hosts, workload security, and lightweight deployments on Kubernetes.

Who Should Watch This​

Platform engineers sizing Wasm hosts should watch Victor Adossi's density results from 12:32 and Liam Randall's comparison with microVMs at 23:59. TypeScript and JavaScript developers will want the Perry and JCO demo starting at 31:10. Security and compliance leads should start with the threat model and Security Slam work at 4:08.

Up Next​

Bailey Hayes aims to bring an outline of the wasmCloud KubeCon workshop to the next call and wants feedback on topics and missing docs. Expect density numbers from the project's bench host now that the host density benchmark has merged, progress on the threat model and Security Insights PRs before the Security Slam ends, and Liam Randall's links comparing sandbox isolation approaches.

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 →