Skip to content

Comparison: connectrpc-axum vs axum-connect

Overview

axum-connect brings the Connect protocol to Axum with an ergonomic API that mirrors Axum's extractor patterns. Created by Alec Thilenius, the latest release is v0.5.3.

Feature Comparison

Featureconnectrpc-axumaxum-connect
Unary RPC (POST)
Unary RPC (GET)
Server streaming
Client streaming
Bidirectional streaming
JSON encoding
Protobuf encoding
Compression (gzip)
Timeouts❌ (TODO)
Message size limits
Error details
Tonic/gRPC interop✅ (optional)
Auto protoc download

API Comparison

connectrpc-axum:

rust
async fn say_hello(
    req: ConnectRequest<HelloRequest>,
) -> ConnectResponse<HelloResponse> {
    ConnectResponse::success(HelloResponse { message: "Hello".into() })
}

HelloWorldServiceBuilder::new()
    .say_hello(say_hello)
    .build_connect()

axum-connect:

rust
async fn say_hello(
    Host(host): Host,
    request: HelloRequest,
) -> Result<HelloResponse, Error> {
    Ok(HelloResponse { message: "Hello".into() })
}

Router::new().rpc(HelloWorldService::say_hello(say_hello))

Key Technical Differences

  • Middleware vs inline: connectrpc-axum uses a Tower layer (ConnectLayer) for protocol handling; axum-connect processes everything inline in generated handlers.

  • Explicit vs ergonomic types: connectrpc-axum wraps requests/responses in ConnectRequest<T>/ConnectResponse<T> for protocol awareness; axum-connect uses raw protobuf types directly.

  • Multi-service composition: connectrpc-axum's MakeServiceBuilder composes multiple services with shared configuration; axum-connect chains .rpc() calls on a single router.

  • Error model: connectrpc-axum supports full Connect error details (additional proto messages); axum-connect has basic error codes only.

Handler Transformation

Both libraries transform user functions into axum-compatible handlers, but use different approaches:

axum-connect uses a macro-based approach:

  • Separate traits for each RPC pattern: RpcHandlerUnary, RpcHandlerStream
  • impl_handler! macro generates trait implementations for each (0-15 extractor parameters)
  • Defines custom RpcFromRequestParts trait (mirrors axum's FromRequestParts)
  • Custom RpcIntoResponse trait for response handling

connectrpc-axum uses a newtype wrapper approach:

  • Unified ConnectHandlerWrapper<F> handles all RPC patterns (unary, server/client/bidi streaming)
  • Compiler selects impl based on handler signature via trait bounds
  • Reuses axum's native FromRequestParts directly (no custom trait)

The key difference: axum-connect requires extractors to implement their RPC-specific traits and separates handler logic by RPC type, while connectrpc-axum uses a single unified wrapper that works with any standard axum extractor.

Summary

connectrpc-axum strengthsaxum-connect strengths
Full streaming support (client + bidi)More ergonomic handler signatures
Tower middleware integrationSimpler learning curve
Compression, timeouts, limitsAuto protoc fetching
Error details supportLess boilerplate for simple cases
Optional Tonic/gRPC interopAutomatic GET variant generation

Released under the MIT License.