Skip to content

RpcServer.Protocol and Socket layer for WebTransport #6247

@kotkoroid

Description

@kotkoroid

What is the problem this feature would solve?

Effect's RPC stack ships HTTP and WebSocket transports. For latency-sensitive real-time work (games, live collab, telemetry), WebSocket is the only persistent option but suffers TCP head-of-line blocking, no unreliable delivery, single-stream multiplexing bottlenecks, and no connection migration across network changes.

WebTransport (HTTP/3/QUIC) solves all four with independent streams, native datagrams, and connection migration. Browser support is broad (Chrome, Edge, Firefox; Safari TP).

Today, picking WebTransport means dropping out of RpcServer.Protocol and Socket entirely and writing a bespoke transport — losing schema-driven RPC, layer-based wiring, and the uniform error model. This feature would make WebTransport a first-class transport so users can match the wire protocol to the workload without abandoning Effect's RPC abstractions.

What is the feature you are proposing to solve the problem?

Add WebTransport as a first-class transport, mirroring the existing WebSocket pair:

  • Server: RpcServer.layerProtocolWebTransport — an RpcServer.Protocol implementation over WebTransport sessions, handling stream-per-request or shared-stream framing and exposing datagrams for unreliable RPCs.
  • Client: Socket.layerWebTransport (+ a Socket.layerWebTransportConstructorGlobal analog) — adapts a browser WebTransport session to the existing Socket interface so RpcClient works unchanged.
  • Schema annotation: a Rpc.unreliable (or equivalent) marker so individual RPCs can opt into datagram delivery; reliable RPCs continue to use QUIC streams.
  • Lifecycle parity: scoped acquire/release that closes the session on layer finalization, matching layerWebSocket semantics.

The goal is drop-in substitutability: an app should be able to swap layerWebSocket for layerWebTransport on both ends and keep its existing RpcGroup definitions, error channels, and layer wiring. Datagram support is the only new surface users opt into explicitly.

What alternatives have you considered?

  • WebSocket + binary framing (msgpack/CBOR): shrinks payloads but doesn't fix head-of-line blocking, datagrams, or connection migration.
  • Hand-rolled WebTransport outside Effect RPC: works, but loses RpcGroup, schema, layers, and uniform errors.
  • WebRTC data channels: offers datagrams but needs SDP/ICE/TURN and a peer model that doesn't fit client/server RPC.
  • HTTP/3 streaming RPC only: gains per-stream independence but no datagrams and no persistent bidirectional session.

Only a first-class layerWebTransport preserves Effect's RPC abstractions while delivering the transport-level wins.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions