connect-rust: One Rust Service, Three RPC Dialects
Anthropic’s Tower-native runtime makes Connect, gRPC, gRPC-Web, and GET feel like the same request path, then backs it up with a spec-first conformance story.

As part of my work at Anthropic, I open sourced two Rust crates that fill a gap in the RPC ecosystem: buffa, a pure-Rust Protocol Buffers implementation with first-class editions support and zero-copy message views, and connectrpc, a Tower-based ConnectRPC implementation that speaks Connect, gRPC, and gRPC-Web on the same handlers.
- connect-rust turns protocol choice into a routing concern, so one Tower service can speak Connect, gRPC, gRPC-Web, and GET without splitting business logic.
- Tower is the real strategic layer here, because it lets connect-rust compose with Axum, Hyper, and middleware instead of becoming a framework island.
- GET support makes unary RPCs look like ordinary web traffic, which opens up browser reach and CDN-friendly caching.
- The conformance suite is the trust signal, because multi-protocol runtimes fail at the edges long before they fail in the happy path.
Most RPC libraries start by asking what wire format you want. connect-rust asks a better question: what if the protocol were just the entrance, not the architecture? One Tower service can accept Connect, gRPC, gRPC-Web, or a browser-friendly GET request, then route them to the same business handler.
The surprising part: one handler, three protocols
That works because the runtime collapses protocol differences early. It sniffs the content type, extracts request metadata, unwraps the envelope stream, and looks up the method path before the handler ever sees a message. By the time your application code runs, the request has already been flattened into a common internal shape.
ConnectRpcService
-> inspect Content-Type
-> extract RequestMetadata
-> decode Envelope stream
-> look up /package.Service/Method
-> dispatch to erased handler
-> encode response for the selected protocol
The shape matters. Once protocol-specific details disappear, the same handler can sit behind Hyper, Axum, or any other Tower stack. Middleware stays middleware, routing stays routing, and RPC becomes one more HTTP service instead of a special subsystem.
Why Tower is the real unlock
This is where connect-rust stops being a protocol adapter and becomes infrastructure. Implementing `tower::Service` means it can live inside the rest of the Rust web ecosystem without pulling the app into a bespoke runtime. Auth, tracing, retries, rate limits, and compression can wrap it in the same way they wrap any other service.
The runtime also threads request state through `http::Extensions`, so upstream layers can attach metadata and handlers can recover it later. That keeps the API small without inventing a parallel context system. The result is a lean RPC layer that still plays well with the rest of the stack.
The GET request is the clue
GET support is the clearest sign that this project is not just gRPC with new branding. For idempotent unary calls, the same RPC can ride a plain browser URL, which opens the door to CDN caching, easier debugging, and less friction at the edge. The handler is still the same, but the delivery path looks like the web because it is the web.
That matters operationally. You can let browser clients and service clients share one contract without teaching the browser a new transport. For a team, that is one less split between internal APIs and public APIs.
Why Anthropic built it this way
Anthropic’s open source pitch is unusually practical. The repo is positioned as a production runtime, not a demo, and the implementation leans on strict lints, spec conformance, and Tower compatibility rather than custom framework tricks. The point is not novelty. The point is repeatable behavior across protocol dialects.
That quote matters because it frames connect-rust as part of a larger stack, not an isolated library. The runtime is one piece of a bigger move toward spec-driven, pure-Rust infrastructure that can absorb protobuf details without locking the whole system to a single transport story.
What it replaces, and what it does not
Against Tonic, the difference is scope. Tonic is a strong gRPC runtime, while connect-rust is trying to unify Connect, gRPC, gRPC-Web, and GET around one handler path. Against Prost and the protobuf Rust stack, the difference is where the value sits. Those are message tools. connect-rust is the request runtime that sits around them.
| Project | Protocol scope | Tower-native | Browser GET | JSON story | Best fit |
|---|---|---|---|---|---|
| connect-rust | Connect, gRPC, gRPC-Web, GET | Yes | Yes | Connect JSON is first-class | One Rust service with shared handlers |
| Tonic | gRPC | Yes | No | Not the core path | Pure gRPC services in the Tower ecosystem |
| Prost | Protobuf codegen | No | No | JSON usually needs extra crates | Message encoding and generated types |
| protobuf v4 Rust stack | Protobuf runtime, no RPC layer | No | No | No RPC layer | Low-level protobuf support |
Why the conformance suite matters
The conformance suite is the credibility layer. In a multi-protocol system, the hardest bugs are not syntax errors. They are edge-case mismatches in framing, metadata, and content negotiation. A suite of 6,558 tests is not marketing. It is how the project keeps the weird edges boring.
That is the real story of connect-rust. It does not just add another Rust RPC option. It turns protocol choice into an HTTP routing detail, then uses Tower, strict conformance, and a very small amount of surface area to make that choice feel ordinary.





