yamux

A lightweight Go library for multiplexing many bidirectional streams over a single TCP or Unix socket connection, with built-in flow control and keepalives.

Library
Go
vv0.1.2
2,670stars
Mozilla Public 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 Activity60
Maintenance36
Community76
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
85/100Excellent
Architecture85
Code Quality90
Innovation88
Learning Curve75

Yamux (Yet another Multiplexer) is a connection multiplexing library for Go, maintained by HashiCorp. It sits on top of any reliable, ordered transport - typically a TCP or Unix domain socket - and lets a single physical connection carry many independent, bidirectional logical streams. Each stream behaves like a standard net.Conn, so existing code that reads and writes to a connection can be adapted to run over a multiplexed stream with minimal changes.

The protocol is inspired by SPDY but is not interoperable with it, and ships with a full specification (spec.md) describing its 12-byte frame header, four message types (data, window update, ping, go-away), and flag-based stream lifecycle (SYN/ACK/FIN/RST). Each stream gets a 256KB flow-control window by default (configurable via MaxStreamWindowSize) to prevent a fast sender from overwhelming a slow receiver, and sessions can be configured with periodic keepalive pings to survive idle load-balanced connections. Yamux underpins RPC forwarding and connection pooling in several HashiCorp tools, including Consul, Nomad, and Vault.

What You Get

  • A Client/Server API that wraps any io.ReadWriteCloser into a multiplexed *Session.
  • Per-stream flow control with a configurable window size to prevent buffer bloat.
  • Optional periodic keepalive pings to detect and recover from dead connections.
  • A documented wire protocol (spec.md) for building interoperable client/server implementations in other languages.
  • Context-aware stream acceptance (AcceptStreamWithContext) and per-stream read/write deadlines.

Common Use Cases

  • RPC frameworks that want to open many logical request/response streams without opening a new TCP connection per call.
  • Reducing connection overhead behind a load balancer or NAT by keeping one long-lived multiplexed connection alive with keepalives.
  • Building bidirectional server-push channels where either side can open new streams, not just the connection initiator.
  • Connection pooling scenarios where memory needs to be reclaimed from idle streams via Stream.Shrink.

Under The Hood

Architecture Yamux is organized as a small, tightly-layered package: mux.go exposes the public Client/Server constructors and Config, session.go implements the *Session orchestration (three goroutines - recv, send, and an optional keepalive - communicating over sendCh, acceptCh, and per-stream notify channels), stream.go implements the *Stream state machine (streamInit through streamEstablished to streamClosed/streamReset, guarded by a stateLock), and const.go defines the wire-level frame header encode/decode plus a handlers slice dispatched by message type. util.go holds small shared primitives (a timer pool, async-notify helpers). The design is intentionally low-level and tightly coupled around the frame format in const.go, which both session.go and stream.go depend on directly - appropriate for a transport-layer library where the wire protocol is the core abstraction.

Tech Stack The library has zero external dependencies - go.mod declares only the module and Go version, with an empty go.sum - and is built entirely on the standard library (net, io, bufio, sync, sync/atomic, encoding/binary, context, time). CI (.github/workflows/test.yaml) runs go fmt, golangci-lint, and go test against both the previous and current stable Go releases, then builds with go build ./…

Code Quality The repository carries an extensive test suite (session_test.go, bench_test.go, const_test.go, util_test.go) covering client/server pairing, timeouts, backlog handling, keepalive failures, and RST/FIN behavior, and CI runs it both with the race detector and with coverage reporting uploaded as an artifact. Errors are explicit, typed sentinel values (ErrSessionShutdown, ErrTimeout implementing net.Error, ErrConnectionReset, and others) that are returned up the call stack rather than logged and swallowed, and the public API follows idiomatic Go naming and godoc conventions throughout.

API Design The public surface is deliberately minimal: two constructors (Client and Server) that accept any io.ReadWriteCloser and an optional *Config with nil-safe defaults, returning a *Session whose Open/Accept methods mirror the standard library’s net.Listener semantics and whose streams satisfy net.Conn directly. This means adopting yamux typically requires changing only how a connection is obtained, not how it is used. Context-aware accept, per-stream deadlines, and a documented spec.md round out an API that is easy to pick up for anyone already comfortable with net.Conn.

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