Library / SDK
connectrpc/connect-rust avatar
connectrpc/connect-rust

connect-rust serves Connect, gRPC and gRPC-Web from one Tower stack

An implementation of the ConnectRPC, gRPC, and gRPC-Web for Rust

531 stars69 forksRustApache-2.0

At a glance

What is it?
connect-rust is a Tower-based Rust implementation of the Connect protocol that also speaks gRPC and gRPC-Web over HTTP with binary or JSON protobuf messages. It suits a Rust service that wants one HTTP surface for several client families, and its API is still pre-1.0.
Who is it for?
connect-rust is worth adopting for a Rust service that has to be reachable by more than one client family, because one Tower stack serves Connect, gRPC and gRPC-Web with the same protobuf messages, and because the workspace ships the health service, the reflection service and the shared google.rpc error types rather than making you assemble them.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One Tower service answers three wire protocols

The architecture is a single HTTP surface that speaks three dialects of the same idea. The project is a Tower-based Rust implementation of ConnectRPC, serving Connect, gRPC and gRPC-Web clients over HTTP with binary or JSON protobuf messages. The choice of Tower as the base is what makes it portable. The runtime is built on `tower::Service`, making it framework-agnostic, and it integrates with any tower-compatible HTTP framework including Axum, Hyper and others. So the service is not tied to one server framework: you write a Tower service, mount it, and the protocol handling sits on top. The workspace manifest confirms the dependency set, with `tower` at 0.5 with the util feature, `tower-http` at 0.6 with catch-panic, the `http` and `http-body` crates at 1, and an async runtime built on `tokio` 1, `tokio-stream`, `tokio-util`, `futures` and `async-trait`.

The workspace is six published crates, not one

The repository root is a Cargo workspace with a set of members, and the split tells you what the project considers separate concerns. There is `connectrpc`, the Tower-based runtime library implementing the Connect protocol, and `connectrpc-codegen`, which backs the `protoc` plugin. There is `connectrpc-build` for `build.rs` integration, so code can be generated at build time rather than checked in. There is `connectrpc-health`, which provides the standard `grpc.health.v1.Health` service, and the documentation says exactly what it is for: `grpc_health_probe`, kubelet gRPC probes and service-mesh health checks. There is `connectrpc-reflection`, the standard gRPC server reflection service for `grpc.reflection.v1` and `v1alpha`, so `grpcurl`, `buf curl`, Postman and `grpcui` can discover and call your services. And there is `connectrpc-types`, the shared `google.rpc` message types, being `Status`, `Code` and the standard error details such as `BadRequest`, `ErrorInfo` and `RetryInfo`, so you can attach them to a `ConnectError` rather than inventing your own error payload. The workspace also includes a `conformance` member and the examples.

Conformance is the measurement, and the numbers are large

The project reports its standing in a way that is unusual and useful, because it names the test suite rather than claiming quality. The status line says the project is pre-1.0, that the API surface is settling but may shift in 0.x, and that the runtime is production-quality, backed by passing the full ConnectRPC conformance suite with 3,600 server and 6,872 client tests across the three protocols. Those are protocol conformance counts, not performance numbers, and the distinction matters. Conformance tells you that a given server implementation answers correctly for a large set of defined cases across Connect, gRPC and gRPC-Web. It does not tell you anything about latency, throughput or how the implementation behaves under a pathological client. The repository root has a `conformance/` directory, so the suite is part of the tree rather than an external dependency.

Code generation has two workflows, and the mount point has to be regenerated

Setting up the codegen is the part with real decisions in it. Two workflows are supported and both produce the same runtime API, so the choice is about your build pipeline. The recommended one for checked-in code is `buf generate`, which runs two codegen plugins, `protoc-gen-buffa` for message types and `protoc-gen-connect-rust` for service stubs, plus `protoc-gen-buffa-packaging` twice to assemble the `mod.rs` module tree for each output directory. The codegen plugins are invoked per-file and only the packaging plugin needs `strategy: all`. The configuration that ties it together is a `buf.gen.yaml`:

yaml
version: v2
plugins:
  - local: protoc-gen-buffa
    out: src/generated/buffa
    opt: [views=true, json=true]
  - local: protoc-gen-buffa-packaging
    out: src/generated/buffa
    strategy: all
  - local: protoc-gen-connect-rust
    out: src/generated/connect
    opt: [buffa_module=crate::proto]
  - local: protoc-gen-buffa-packaging
    out: src/generated/connect
    strategy: all
    opt: [filter=services]

The `buffa_module=crate::proto` option tells the service-stub generator where you mounted the buffa output, and for a method input type `greet.v1.GreetRequest` it emits `crate::proto::greet::v1::GreetRequest`. The second packaging invocation uses `filter=services` so the connect tree's `mod.rs` only includes files that actually have service stubs in them. Changing the mount point requires regenerating, which the documentation states plainly.

Three ways to get the plugin, and one of them needs no local install

The `protoc-gen-connect-rust` plugin can be obtained in three ways, and the choice affects your build's reproducibility. The first is a pre-built binary from the GitHub release, with binaries for Linux on x86_64 and aarch64, macOS on x86_64 and aarch64, and Windows on x86_64. The download block in the documentation is thorough about verification, fetching the binary, a `.sig` and a `.pem`, and a checksum file, then checking the SHA-256 and either the GitHub-native attestation or the cosign signature directly before installing to `/usr/local/bin`. The second is building from source with `cargo install --locked connectrpc-codegen`, which pulls the latest published codegen crate from crates.io and installs the binary into `$CARGO_HOME/bin`. The third is the Buf Schema Registry remote plugin, published as `buf.build/connectrpc/rust` with versions tracking connect-rust releases, where no local install is needed because you replace the `local: protoc-gen-connect-rust` entry with a `remote: buf.build/connectrpc/rust:v0.9.0` one. The message types themselves come from the `buffa` project, whose release page offers binaries or a cargo install.

The generated modules are mounted by hand into your crate

The output of codegen is not automatically part of your crate, and the mounting is explicit. The documented result in `src/lib.rs` is:

rust
#[path = "generated/buffa/mod.rs"]
pub mod proto;
#[path = "generated/connect/mod.rs"]
pub mod connect;

Two path attributes and two module declarations, which is the whole integration on the Rust side. There is a constraint underneath it that is worth reading before you pin versions. The workspace manifest states that the 0.9.x floor on the underlying protobuf crate is hard rather than a preference, for two reasons: 0.9.0 widens `types::put_len_delimited_header` and the `map_codec::field_len` accumulator to `u64`, so code emitted by a 0.8.x codegen does not compile against a 0.9 runtime, and the codegen paths call `buffa_codegen::decode_request` and `tooling_decode_options`, which arrived in 0.9.1. The manifest also notes that the regen baseline for the checked-in generated code is the buffa version in Cargo.lock rather than that floor, so bumping the lock and regenerating is the supported path.

Where a pre-1.0 RPC runtime is the wrong bet

Two limits are worth stating. The first is the stability of the surface, and the project says it itself: the API is pre-1.0, the surface is settling, and it may shift in 0.x. For an internal service that you own end to end, that is a manageable risk, because the breakage and the fix are both in your repository. For a library that other teams call, or a service whose clients you do not control, an API that can change under a minor version is a real cost, and the migration work falls on whoever upgrades. The second is the toolchain, which is heavier than a plain Rust crate. The workspace pins the edition to 2024 and the rust-version to 1.88, the MSRV is Rust 1.88 declared on the workspace and verified in CI, and the codegen path involves a `protoc` plugin, a separate `buffa` generator, and a packaging step, with a buf configuration file. The alternative to weigh against is tonic, the gRPC-focused Rust implementation, and the difference in approach is exactly the surface area. tonic speaks gRPC, and gRPC-Web and Connect are things you add with additional layers. connect-rust speaks all three from one stack, so a browser client and a native gRPC client hit the same service, and the price is the wider pre-1.0 surface and the codegen pipeline. If your clients are all gRPC, tonic is the smaller commitment. If one of them is a browser, connect-rust removes a translation layer that you would otherwise have to build.

Editorial conclusion

connect-rust is worth adopting for a Rust service that has to be reachable by more than one client family, because one Tower stack serves Connect, gRPC and gRPC-Web with the same protobuf messages, and because the workspace ships the health service, the reflection service and the shared google.rpc error types rather than making you assemble them. It is a poor fit if you need a stable API, because the project states plainly that it is pre-1.0 and that the API surface is settling but may shift in 0.x, and a poor fit if your clients are gRPC-only and you have no browser clients, since then the extra protocol coverage buys you nothing. Before adopting it, read the user guide for the code generation workflow you intend to use, check that the buffa version in Cargo.lock matches the one your generated code was produced with, and note that the last push to the repository was on 2026-10-22 with the most recent release v0.9.1 published on 2026-09-21.

Frequently asked questions

What protocols does connect-rust serve?

It is a Tower-based Rust implementation of ConnectRPC that serves Connect, gRPC and gRPC-Web clients over HTTP with binary or JSON protobuf messages. The runtime is built on tower::Service, so it is framework-agnostic and integrates with any tower-compatible HTTP framework including Axum and Hyper.

How do I generate the Rust code for a connect-rust service?

Two workflows are supported. The recommended one for checked-in code is buf generate, which runs protoc-gen-buffa for message types, protoc-gen-connect-rust for service stubs and protoc-gen-buffa-packaging twice to assemble the module tree. The alternative is connectrpc-build, which generates the code at build time from build.rs.

Do I have to install the protoc plugin locally?

No. The plugin is published on the Buf Schema Registry as buf.build/connectrpc/rust with versions tracking connect-rust releases, so you can replace the local: protoc-gen-connect-rust entry with remote: buf.build/connectrpc/rust:v0.9.0. You can also download a signed pre-built binary, or run cargo install --locked connectrpc-codegen to build it from source.

Is connect-rust ready for production use?

The project states it is pre-1.0, that the API surface is settling but may shift in 0.x, and that the runtime is production-quality, passing the full ConnectRPC conformance suite with 3,600 server and 6,872 client tests across the three protocols. The minimum supported Rust version is 1.88.

Official sources

  1. connectrpc/connect-rust on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/connectrpc-connect-rust.svg)](https://hysenlabs.com/projects/connectrpc-connect-rust)

Was this useful?