Runtime compatibility
Which JavaScript APIs and npm packages have been tested in Sproutboat handlers.
Sproutboat’s JavaScript and npm compatibility comes from Porffor’s compiler and runtime work, together with Sproutboat’s architecture: the CLI bundles and checks imports, and the native host supplies HTTP and bindings. The result is a compiled handler with a specific API surface, not a Node or Deno runtime. A package working in Porffor alone does not establish that it works in a Sproutboat handler, or vice versa.
The results below concern code inside the handler. The CLI’s build environment has a different set of APIs. A successful bundle is only the first step: an imported package must also compile and behave correctly in the native sprout.
Runtime APIs
| Surface | Handler support | Scope |
|---|---|---|
| JavaScript and Web APIs | Partial | Common synchronous JavaScript, URL, Request, Response, Headers, FormData, text encoding, the Cache API and selected crypto operations work. See The handler for the tested surface. |
| Sproutboat bindings | Supported where documented | Use env.* for storage, secrets, and other configured services. Binding calls are synchronous before the compatibility date that makes each one return a Promise (D1 2026-10-24, KV 2026-10-25, R2 2026-10-26); see Bindings. |
| Node APIs | Limited | node:path, node:url and node:querystring imports work through built-in shims. Other Node built-ins, process, Buffer, require() and filesystem access are unavailable. |
| Deno APIs | Unsupported | The Deno global and Deno runtime APIs are unavailable. Standard Web APIs used by Deno code may work when listed here. |
| Web Streams | Tested in memory | ReadableStream, WritableStream and TransformStream support reading, piping, transforms, tee, cancellation and BYOB reads. HTTP bodies remain buffered; stream BodyInit and progressive responses are unsupported. |
| WebSockets | Unsupported | No WebSocket handler in the current http-sync-v0 profile. |
Proxy |
Tested operations | CLI 0.17.0 uses Porffor alpha-17, retaining alpha-16 Proxy support. Native checks cover object traps, function calls, construction, revocation and a frozen-property invariant. Package support remains specific to the operations tested below. |
Performance
The runtime comparison runs the same Worker-style app on Node, workerd and a released Sproutboat executable on one Linux host, with raw samples and the method linked from the results.
npm package results
These results were checked on 2026-09-25 with CLI 0.11.12, using native standalone builds. The three packages that failed were rechecked on 2026-09-30 with CLI 0.12.0. “Passed” means the listed operation returned the expected result in that test. It does not certify every export, input, dependency version, or deployment mode of the package.
| Package | Version | Tested operation | Result |
|---|---|---|---|
cookie |
2.0.1 | Parse and serialize cookies | Passed |
path-to-regexp |
8.4.2 | Match a route | Passed |
hono |
4.13.9 | Answer a simple route | Passed; broader Hono behavior untested |
valibot |
1.5.0 | safeParse |
Passed |
zod |
4.6.5 | safeParse with valid and invalid object input |
Passed; broader Zod behavior untested |
nanoid |
6.0.1 | Generate an ID | Passed |
uuid |
14.0.2 | Generate a v4 ID | Passed |
ms |
2.1.3 | Parse a duration | Passed |
date-fns |
4.4.0 | Format an epoch timestamp | Passed |
is-path-inside |
4.0.0 | Check a nested, sibling and identical path | Passed, through the node:path shim |
qs |
6.16.0 | Nested query parse and stringify | Passed with CLI 0.16.0 |
itty-router |
5.0.24 | IttyRouter: GET parameters, Unicode POST body and 404 fallback |
Passed with CLI 0.16.0; standard Router still fails to compile around labelled iterator breaks |
@trpc/server |
11.19.0 | initTRPC, router and createCaller().hello() |
Passed with CLI 0.16.0; HTTP adapters, clients, middleware and subscriptions untested |
better-auth |
1.7.1 | Email/password signup, signed-cookie session lookup, wrong-password rejection, signin, signout and revocation | Passed with an explicit memory adapter and default hashing; see limits below |
mime-types |
3.0.2 | Bundle | Failed: calls require("path") |
The qs, itty-router and tRPC probes were checked on 2026-10-10 with CLI 0.16.0, using native standalone builds. Collection iterator methods and matchAll now expose next() and done. URLSearchParams and FormData support live iteration, including entries appended after creating the iterator. String iteration still splits emoji and other astral characters into UTF-16 halves.
Better Auth was checked on 2026-10-11 using an optimized native standalone build and pinned dependencies, including noble hashes 2.4.0 and zod 4.6.5. The memory adapter is test storage; production database adapters, OAuth and plugins are untested. Default password hashing takes about six seconds on the development machine. Database-free sessions select encrypted JWE and still require unsupported AES. The repeatable fixture is in the CLI integration probe.
Alpha 17 fixes number conversion, Math.round ties and signed zero, console precision and class-field captures. The newer unreleased TextEncoder commit passes native Unicode checks and may replace our encoder patch in the next release. See the upgrade audit.
These are deliberately narrow results. In particular, a simple Hono route does not establish that every Hono feature works, and Zod’s basic validation result does not establish compatibility for packages built on Zod.
Check a dependency for your handler
- Pin the package version and import the operations you actually use from your handler.
- Run
sproutboat checkandsproutboat build --standalone. A passing check alone does not prove native runtime behavior. - Run the standalone sprout and send requests that cover both success and failure paths. Repeat on the deployed platform if your code uses broker-backed bindings.
When reporting a failure, include the CLI and package versions, the smallest handler that reproduces it, whether bundling, compilation, startup, or a request failed, and whether it occurred in standalone or deployed mode. This helps distinguish an upstream Porffor limitation from a Sproutboat bundle, shim, or binding issue.