Skip to content

JS/TS SDK can't run on Cloudflare Workers (edge runtime): gRPC-over-HTTP/2 transport is unsupported #4124

Description

@0x0f0f0f

Summary

Summary

modal@0.9.0 cannot run inside a Cloudflare Worker (or Durable Object) — the same edge/V8-isolate constraint that affects Vercel Edge, Deno Deploy, etc. It works fine in a Node process, including a Cloudflare Container (full Linux/Node runtime). The blocker is the gRPC transport: nice-grpc@grpc/grpc-js speaks gRPC over HTTP/2 with bidirectional streaming, which the Workers runtime does not support even with nodejs_compat + node:http2 enabled.

Is a Workers-compatible (fetch/Connect/gRPC-Web) transport on the roadmap?

Environment

  • modal 0.9.0 (JS/TS SDK)
  • Target runtime: Cloudflare Workers / Durable Objects (workerd), nodejs_compat, compat date ≥ 2026-03-17 (so enable_nodejs_http2_module is auto-on)
  • Auth: explicit MODAL_TOKEN_ID / MODAL_TOKEN_SECRET (no ~/.modal.toml)

What happens

Instantiating a client / making any RPC fails inside the Worker: @grpc/grpc-js cannot establish a working HTTP/2 channel to api.modal.com. The SDK also imports node:fs/node:os (config loading), which are unavailable/partial on the edge, but those are avoidable by passing tokens explicitly — the transport is the hard blocker.

Root cause

  1. The SDK's transport is Node gRPC: dependencies include nice-grpc and protobufjs; the built bundle imports node:fs, node:fs/promises, node:os, node:crypto, node:stream, and calls createChannel / ChannelCredentials from nice-grpc.
  2. nice-grpc (Node variant) runs on @grpc/grpc-js, which requires HTTP/2 with client-streaming / bidirectional streaming.
  3. Cloudflare Workers do not support outbound HTTP/2 bidirectional streaming. Even with a compat date ≥ 2026-03-17 (where enable_nodejs_http2_module auto-enables node:http2), that module is stubbed and bidi streaming is unimplemented. Tracked upstream:
  4. grpc-js also opens raw node:net / node:tls sockets; Workers only permit outbound connections via fetch() or connect() from cloudflare:sockets, which grpc-js does not use.

Why it works in a Cloudflare Container (our current workaround)

A Cloudflare Container is a real Linux/Node runtime with functional http2/net/tls/fs, so nice-grpc/grpc-js behave exactly as on any Node server. We run the Modal-facing orchestrator in a Container fronted by a Durable Object and bind it into the Worker, instead of calling Modal directly from the Worker. It works, but it means we can't do the lightweight thing (call Modal straight from an edge Worker) and pay for a container to sit in the request path.

Possible fixes (SDK side)

  • A fetch-based / Connect transport. A Connect protocol or nice-grpc-web transport over standard fetch would run on Workers (and every edge runtime + browsers). This requires Modal's control plane to expose a gRPC-Web/Connect endpoint (Connect-native server or an Envoy/grpc-web proxy). Caveat: gRPC-Web/Connect support unary + server-streaming but not client/bidi streaming — so any RPCs Modal relies on for bidi streams (interactive exec, log tailing) would need a server-streaming or chunked-fetch fallback.
  • Pluggable transport + runtime detection. Let callers inject a transport, and make config file loading (node:fs/node:os) lazy/optional so merely importing the SDK with explicit tokens doesn't touch the filesystem. That at least unblocks bundling on the edge.
  • Document the constraint. A short note in the JS SDK docs ("runs on Node ≥ 22; not on edge/isolate runtimes — gRPC/HTTP2 transport") would save others the investigation.

Fix (Cloudflare side, out of Modal's hands)

Track cloudflare/workerd#6455 (HTTP/2 bidi streaming). If/when that lands, grpc-js may work under nodejs_compat with no SDK change.

Related

Version

0.9.0

App ID

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions