Skip to content

CLOUDFLARE

Read original ↗

Cloudflare Workers and Containers now support inbound TCP connections and gRPC

Summary

Cloudflare extends Workers with inbound TCP socket support via a new connect(socket) handler and adds multiple paths for running gRPC applications on the platform. The connect() handler receives an inbound TCP socket from Spectrum (Cloudflare's ingress proxy for non-HTTP traffic) and can pass it to other Workers, Durable Objects, or Containers — enabling full-duplex, bidirectional communication for any TCP-based protocol, in any language. For gRPC specifically, three options are now available: (1) full bidirectional gRPC via Containers with raw TCP passthrough, (2) unary + server-streaming gRPC served directly from Workers using gRPC-web with automatic protocol translation, and (3) Workers calling external gRPC servers with transparent gRPC-web→gRPC conversion.

Key Takeaways

  1. New connect(socket) handler in the Workers runtime accepts an inbound TCP socket provided by Spectrum; the socket is a standard ReadableStream/WritableStream pair that can be piped, forwarded, or processed inline.

  2. Socket routing chain: a Worker can pass the socket to another Worker, to a Durable Object (via stub.connect("host:port")), or from a Durable Object to its Container (via this.ctx.container!.getTcpPort(8080).connect("10.0.0.1:8080")). This gives full control over the path from client to server.

  3. Spectrum as TCP ingress: a new type of Spectrum application routes incoming TCP connections to a specified Worker rather than directly to an origin — Spectrum is Cloudflare's existing ingress proxy for non-HTTP traffic already handling TCP and UDP applications.

  4. Bidirectional gRPC from Containers: using the TCP socket passthrough, any gRPC server (any language, any dependencies) can run inside a Cloudflare Container and receive full-duplex bidirectional streaming over a single persistent connection. The example shows a Go gRPC server with bidirectional Chat streaming.

  5. Workers as gRPC servers without containers: for simpler use cases (unary + server-streaming), Workers can serve gRPC APIs using the @connectrpc/connect package. Cloudflare automatically translates incoming gRPC (HTTP/2 framed) to gRPC-web at the edge and translates outgoing gRPC-web back to gRPC — clients don't need changes.

  6. gRPC-web as the Workers-side protocol: web browsers can't expose HTTP/2 frame-level control or raw TCP, which is why gRPC-web exists. Cloudflare has performed gRPC↔gRPC-web conversion in its reverse proxy since 2020 (documented in their "Road to gRPC" post); this is now extended to let Workers serve and call gRPC via the gRPC-web intermediate form.

  7. Use cases enabled: (a) mobile apps with existing gRPC native clients (grpc-swift-2, grpc-kotlin) can now use a Workers backend; (b) Workers can sit in front of existing gRPC backends as an edge proxy (same pattern as REST-behind-Workers); (c) real-time voice AI with low-latency bidirectional streaming deployed to 330+ Cloudflare locations.

  8. Private beta launch — all features described are in private beta with a signup form; gRPC-web conversion will roll out to everyone after the beta period.

  9. Cloudflare's own RPC position: internally Cloudflare uses Cap'n Proto and Cap'n Web (their JavaScript-native RPC system), not gRPC. This launch is explicitly customer-demand-driven for the existing gRPC ecosystem.

Architectural Details

Socket Routing Topology

Client → Spectrum (TCP ingress) → Worker [connect(socket)]
                                      ↓ stub.connect()
                                  Durable Object [connect(socket)]
                                      ↓ ctx.container!.getTcpPort()
                                  Container (any language, any protocol)

gRPC Translation Architecture

gRPC Client (HTTP/2) → Cloudflare Edge [gRPC → gRPC-web conversion]
                           → Worker [gRPC-web handler via @connectrpc/connect]
                           → Response [gRPC-web → gRPC conversion] → Client

For outbound calls:

Worker [@connectrpc/connect client, gRPC-web] → Cloudflare Edge [gRPC-web → gRPC] → External gRPC server

Key Technical Distinction

HTTP/2 splits requests/responses into frames with stream IDs for multiplexing. gRPC depends on this stream-level control for streaming, cancellation, flow control, and trailers. Web platform APIs like fetch() don't expose frame-level access — hence the gRPC-web intermediate layer that encodes the same semantics into HTTP/1.1-compatible framing.

Caveats

  • Private beta — no SLA, no performance numbers, no GA timeline disclosed.
  • No latency measurements for the socket routing chain (Worker → DO → Container hop costs).
  • UDP-based protocol support mentioned as future direction but not shipped.
  • gRPC-web translation for Workers only supports unary + server-streaming; client-streaming and bidirectional-streaming require the Container path with raw TCP passthrough.
  • Protobuf definition file required for the gRPC-web approach (code generation via @connectrpc/connect).

Source

Last updated · 608 distilled / 1,858 read