ttrpc

A low-overhead GRPC-like RPC framework for Rust built for low-memory container runtimes.

Library
Cargo
v0.9.0
365stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
68/100Good
Development Activity76
Maintenance36
Community80
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
62/100Good
Architecture70
Code Quality62
Innovation60
Learning Curve55

ttrpc is the Rust implementation of the ttrpc protocol, a lightweight GRPC-style RPC framework designed by the containerd project for environments where memory and CPU headroom are scarce, such as container runtime shims, VM agents, and sandboxed init processes. It reuses Protocol Buffers for message definitions and code generation but replaces gRPC’s HTTP/2 transport with a minimal length-prefixed framing protocol over Unix domain sockets or vsock, cutting the runtime and dependency footprint that a full HTTP/2 stack would impose.

The crate ships both a synchronous, thread-based client/server implementation and an async/await implementation gated behind feature flags, plus a protoc plugin and a ttrpc-codegen crate for generating Rust service stubs from .proto files. It is a foundational dependency inside the containerd ecosystem, used by runc-adjacent shims, Kata Containers’ agent protocol, and other low-level container tooling that needs an RPC channel between a host process and a guest or sandboxed process without the overhead of a full gRPC stack.

What You Get

  • Synchronous client and server built on OS threads and mpsc channels, enabled by the default sync feature
  • Async/await client and server built on Tokio, enabled by the optional async feature, including async streaming support
  • A protoc compiler plugin (ttrpc_rust_plugin) and a ttrpc-codegen crate for generating Rust request/response types and service traits from .proto files
  • Unix domain socket, abstract Unix socket, and vsock transport support on Linux, with named-pipe support on Windows
  • A Context type for per-call metadata and timeouts, plus a typed Error/Status/Code model compatible with gRPC-style status codes

Common Use Cases

  • Implementing the OCI/containerd shim protocol between a container runtime and its per-container shim process
  • Building the guest agent RPC channel for VM-based sandboxes (e.g. Kata Containers) where the host talks to a lightweight in-guest agent over vsock
  • Any host-to-sandboxed-process or daemon-to-plugin RPC channel in Rust that needs gRPC-like ergonomics without pulling in a full HTTP/2 client/server stack
  • Low-memory embedded or edge daemons that need structured RPC over Unix sockets rather than a bespoke text protocol

Under The Hood

Architecture: The crate splits into two parallel implementations behind Cargo feature flags — sync (default) and async — sharing a common proto module (generated Protobuf types plus MessageHeader/Codec framing logic in src/proto.rs) and error/context modules. In the sync path (src/sync/client.rs, src/sync/server.rs), Client::new_client spawns a dedicated sender thread that pulls (buf, reply_channel) pairs off an mpsc::Sender and writes framed messages to the socket, and a receiver thread that reads response frames and dispatches them to a HashMap<stream_id, SyncSender> guarded by a Mutex; the async path (src/asynchronous/) replaces the threads with Tokio tasks and adds a stream.rs module for bidirectional streaming and a shutdown.rs module for graceful connection teardown. Transport selection (Unix socket, abstract socket, vsock, or Windows named pipe) is resolved from a sockaddr string prefix and abstracted behind a sys module per platform.

Tech Stack: Core dependencies are protobuf (message encode/decode and codegen, workspace-pinned to 3.7.2), thiserror for the Error enum, nix/windows-sys for platform socket primitives, and crossbeam/log. The optional async feature pulls in tokio (rt, sync, io-util, macros, time, net), async-trait, async-stream, futures, and tokio-vsock on Linux/Android. The workspace also builds a compiler crate (the legacy protoc-gen-ttrpc plugin) and a ttrpc-codegen crate (a programmatic codegen API for build.rs), both versioned and released alongside the core ttrpc crate. Edition 2018, MSRV 1.70, license Apache-2.0.

Code Quality: Unit tests exist but are sparse and localized — 11 #[test] functions total, concentrated in src/proto.rs, src/context.rs, src/common.rs, and the Windows net module, with no tests in the sync or async client/server modules themselves; correctness there is exercised indirectly via tests/run-examples.rs, which runs the example/ binaries end-to-end. Error handling is consistent throughout, funneled through a single thiserror-derived Error enum (Socket, RpcStatus, Nix/Windows, LocalClosed, RemoteClosed, Eof, Others) with a project-wide err_to_others_err! macro for wrapping foreign errors, though several Mutex::lock().unwrap() calls and a couple of comment-documented invariants (e.g. weak-Arc use in the receiver thread) rely on careful manual reasoning rather than the type system to stay safe.

API Design: The public surface is small and gRPC-familiar — Client::connect, Server, MethodHandler, and a Context carrying metadata/timeout — but getting started requires an external toolchain step (installing protoc and the ttrpc_rust_plugin, or wiring ttrpc-codegen/protoc_rust_ttrpc::Codegen into build.rs) before any service code compiles, and the README’s setup instructions are terse relative to that complexity. Sync and async APIs are separate feature-gated modules with overlapping but not identical shapes, so switching between them mid-project requires re-reading both APIs rather than flipping one flag.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search