You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@tschneidereit and I have had informal discussions about host implementations reusing a given instance to handle multiple incoming requests by default for wasi:http@0.3.0 and beyond, and currently Wasmtime does this.
However, I don't know that this has been documented anywhere in the spec, nor do we yet have clear guidelines on how a component could opt out of reuse (e.g. with some combination of backpressure.dec, graceful shutdown, and wasi:cli/exit#exit). This would be helpful for both host and guest implementors.
Note that I'm mostly thinking of inbound wasi:http handlers here, but reuse can also be relevant for arbitrary components, so I'm not totally sure where this sort of thing should be specified.
Also note that this overlaps with, but is distinct from, #807, which concerns instances meant to run indefinitely, whereas this is about hosts reusing instances only a short time as an optimization which guest components should not rely heavily on for correctness.
I'll add that I found navigating this space to be a bit challenging to sort out without documentation and there seems to potentially be a gap in being able to clearly and correctly express 3 different cases for instance reuse using wasi-http (and latest wasmtime serve).
The cases I tried to demonstrate in my test were the following, along with notes. There's very likely to be some user error here as I am just working to come more completely up to speed on some aspects of cm async and the p3 proposals:
Concurrent instance reuse (the default).
Serial instance reuse (one request at a time, but same instance).
I was able to show this working by having handle increment backpressure on entry and decrement.
This worked in my test case, but it wasn't entirely clear that this would unequivocally prevent a host from concurrently starting another asynchronous request (let's say two requests had come in). Would this be something guaranteed by the spec such that it would be incorrect for a host do this.
I did experiment with having a guest where the wit-bindgen export was "-" to do a sync lift; this compiled but did not work with wasmtime serve and wit-bindgen 0.55.0 1. This might be a wit-bingen issue, but I haven't dug in deep.
No reuse (process one request and terminate).
I couldn't get a version of this to work (without changing the host to work in this mode).
Footnotes
Logs or sync lift case; I can share the full example if it is useful -- pretty basic handler that is an async fn with wit-bindgen having the export as "-export:wasi:http/handler@0.3.0-rc-2026-03-15#handle".
Guest log:
[sync-lift] iid=0x831ad21dec08c719 req=01 START
[sync-lift] iid=0x831ad21dec08c719 req=01 END
thread '<unnamed>' (1) panicked at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/waitable.rs:193:13:
assertion failed: !task.is_null()
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
worker error: error while executing at wasm backtrace:
0: 0xb9f3 - abort
at wasisdk://v30.0/build/sysroot/wasi-libc-wasm32-wasip2-build-prefix/src/wasi-libc-wasm32-wasip2-build-build/wasisdk://v30.0/src/wasi-libc/libc-bottom-half/sources/abort.c:5:3
1: 0x92f3 - std[d123b7a1a2ed1472]::sys::pal::wasi::helpers::abort_internal
at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/pal/wasi/helpers.rs:4:14
2: 0x8426 - std[d123b7a1a2ed1472]::process::abort
at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/process.rs:2533:5
3: 0x89f8 - __rustc[b7974e8690430dd9]::__rust_abort
at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/rt.rs:33:5
4: 0x74a9 - __rustc[b7974e8690430dd9]::__rust_start_panic
at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/panic_abort/src/lib.rs:50:5
5: 0x8825 - __rustc[b7974e8690430dd9]::rust_panic
at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:886:25
6: 0x7c9a - std[d123b7a1a2ed1472]::panicking::panic_with_hook
at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:850:5
7: 0x787a - std[d123b7a1a2ed1472]::panicking::panic_handler::{closure#0}
at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:691:13
8: 0x780d - std[d123b7a1a2ed1472]::sys::backtrace::__rust_end_short_backtrace::<std[d123b7a1a2ed1472]::panicking::panic_handler::{closure#0}, !>
at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/backtrace.rs:182:18
9: 0x8adb - __rustc[b7974e8690430dd9]::rust_begin_unwind
at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:689:5
10: 0x1057c - core[6d9e98711c484d2e]::panicking::panic_fmt
at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:80:14
11: 0x103c9 - core[6d9e98711c484d2e]::panicking::panic
at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:150:5
12: 0x4dd6 - wit_bindgen::rt::async_support::waitable::WaitableOperation<S>::register_waker::hde47cb997528dce8
at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/waitable.rs:193:13
- wit_bindgen::rt::async_support::waitable::WaitableOperation<S>::poll_complete_with_code::hd22a90f526e6d1de
at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/waitable.rs:338:18
13: 0x57a5 - wit_bindgen::rt::async_support::waitable::WaitableOperation<S>::poll_complete::h605a2b23cc93fc87
at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/waitable.rs:293:14
14: 0x5c81 - <wit_bindgen::rt::async_support::future_support::RawFutureWrite<O> as core::future::future::Future>::poll::hc72fcaed7ea6645c
at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/future_support.rs:716:14
- <wit_bindgen::rt::async_support::future_support::RawFutureWriter<O>::write_and_forget::DeferredWrite<O> as alloc::task::Wake>::wake::he1249cadca69f382
at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/future_support.rs:554:62
15: 0x5a79 - wit_bindgen::rt::async_support::future_support::RawFutureWriter<O>::write_and_forget::h235167da4f91e4a1
at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/future_support.rs:506:10
- <wit_bindgen::rt::async_support::future_support::FutureWriter<T> as core::ops::drop::Drop>::drop::hcaaad8d86644138a
at /Users/paul.osborne/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/wit-bindgen-0.55.0/src/rt/async_support/future_support.rs:379:17
- core::ptr::drop_in_place<wit_bindgen::rt::async_support::future_support::FutureWriter<core::result::Result<core::option::Option<wasi_http_concurrency_guest::wasi::http::types::Fields>,wasi_http_concurrency_guest::wasi::http::types::ErrorCode>>>::h606931453b035b43
at /Users/paul.osborne/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:805:1
- core::mem::drop::hf433209343d7ac34
at /Users/paul.osborne/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/mem/mod.rs:975:1
- <wasi_http_concurrency_guest::Component as wasi_http_concurrency_guest::exports::wasi::http::handler::Guest>::handle::h74ebd70f1b9d8869
at /Users/paul.osborne/Projects/Fastly/compute-p3-examples/wasi-http-concurrency/guest/src/lib.rs:204:9
16: 0x2218 - wasi_http_concurrency_guest::exports::wasi::http::handler::_export_handle_cabi::h30c4ecad9fbc835d
at /Users/paul.osborne/Projects/Fastly/compute-p3-examples/wasi-http-concurrency/guest/src/lib.rs:90:1
17: 0x62a2 - wasi:http/handler@0.3.0-rc-2026-03-15#handle
at /Users/paul.osborne/Projects/Fastly/compute-p3-examples/wasi-http-concurrency/guest/src/lib.rs:90:1
error: channel closed
Stack backtrace:
0: <std::backtrace::Backtrace>::capture
1: hyper::proto::h1::dispatch::Dispatcher<D,Bs,I,T>::poll_loop
2: wasmtime_cli::commands::serve::ServeCommand::serve::{{closure}}::{{closure}}
3: tokio::runtime::task::raw::poll
4: tokio::runtime::scheduler::multi_thread::worker::Context::run_task
5: tokio::runtime::task::raw::poll
6: std::sys::backtrace::__rust_begin_short_backtrace
7: core::ops::function::FnOnce::call_once{{vtable.shim}}
8: <std::sys::thread::unix::Thread>::new::thread_start
9: __pthread_cond_wait
This worked in my test case, but it wasn't entirely clear that this would unequivocally prevent a host from concurrently starting another asynchronous request (let's say two requests had come in). Would this be something guaranteed by the spec such that it would be incorrect for a host do this.
Yes, signaling backpressure is meant to guarantee that no additional requests will be sent to the instance, and I believe that's what's implemented for wasmtime serve.
No reuse (process one request and terminate).
* I couldn't get a version of this to work (without changing the host to work in this mode).
You should be able to opt out of reuse in the guest by calling exit, after which the guest can't be assumed to be in a good state to continue running.
This might be a wit-bingen issue, but I haven't dug in deep.
Yeah this is a wit-bindgen issue having to do with and async function expecting ambient state to be configured but it's not because it wasn't entered from an async context. Something we definitely need to improve for wit-bindgen. If you're willing would you be up for filing an issue on wit-bindgen? No need to be too too detailed.
Activity
posborne commentedon May 12, 2026
I'll add that I found navigating this space to be a bit challenging to sort out without documentation and there seems to potentially be a gap in being able to clearly and correctly express 3 different cases for instance reuse using wasi-http (and latest
wasmtime serve).The cases I tried to demonstrate in my test were the following, along with notes. There's very likely to be some user error here as I am just working to come more completely up to speed on some aspects of cm async and the p3 proposals:
handleincrement backpressure on entry and decrement.wasmtime serveandwit-bindgen0.55.0 1. This might be a wit-bingen issue, but I haven't dug in deep.Footnotes
Logs or sync lift case; I can share the full example if it is useful -- pretty basic handler that is an async fn with wit-bindgen having the export as
↩"-export:wasi:http/handler@0.3.0-rc-2026-03-15#handle".tschneidereit commentedon May 12, 2026
Yes, signaling backpressure is meant to guarantee that no additional requests will be sent to the instance, and I believe that's what's implemented for
wasmtime serve.You should be able to opt out of reuse in the guest by calling exit, after which the guest can't be assumed to be in a good state to continue running.
alexcrichton commentedon May 12, 2026
Yeah this is a wit-bindgen issue having to do with and
asyncfunction expecting ambient state to be configured but it's not because it wasn't entered from an async context. Something we definitely need to improve for wit-bindgen. If you're willing would you be up for filing an issue on wit-bindgen? No need to be too too detailed.posborne commentedon May 12, 2026
@tschneidereit It turns out
cli:exitwas working. Thewasmtime servehost was logging clean exits as errors which mislead me.bytecodealliance/wasmtime#13345 patches the logging behavior.
tschneidereit commentedon May 13, 2026
Ah yes, I keep running into that and meaning to file an issue for it. Would you mind opening one?
wasi-http: fix issues with exit pattern and response completion futures