# smallnest/rpcx: a Go RPC framework where plain methods become services

> rpcx is a Go microservices RPC framework in the Dubbo tradition. It skips proto files, supports TCP, HTTP, QUIC and KCP, and ships service discovery, load balancing and fault tolerance as pluggable pieces. Here is how it installs, what the plugin split means for upgrades, and where it is the wrong tool.

**smallnest/rpcx** — Best microservices framework in Go, like alibaba Dubbo, but with more features, Scale easily. Try it. Test it. If you feel it's better, use it! 𝐉𝐚𝐯𝐚有𝐝𝐮𝐛𝐛𝐨, 𝐆𝐨𝐥𝐚𝐧𝐠有𝐫𝐩𝐜𝐱! build for cloud!

- Repository: https://github.com/smallnest/rpcx
- Website: https://rpcx.io
- Stars: 8,319 · Forks: 1,179
- Language: Go
- License: NOASSERTION
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/smallnest-rpcx

## The problem rpcx removes: proto files and the codegen step between them

Most Go RPC stacks ask you to describe the interface twice. Once in a schema file, then again as generated Go types that you call from both sides. rpcx inverts that. The README states plainly that the framework supports "raw Go functions" and that "There's no need to define proto files." You write a struct, export methods on it, register it with a server, and a client invokes those methods by name.

That is the whole pitch, and it is aimed at a specific reader. If your services are Go on both ends, the schema file is mostly ceremony you pay for at build time and in CI. Removing it means a new endpoint is a method plus a registration call, not a schema edit, a regeneration, and a review of the generated diff. The cost of that trade shows up later: there is no schema to hand to a service written in another language, so cross-language callers depend on the raw protocol path described below.

The framework positions itself against Alibaba Dubbo, and the comparison is structural rather than cosmetic. Dubbo's ecosystem assumes a registry, an interface registry and a governance layer around Java services. rpcx keeps the registry and governance vocabulary but drops the interface-definition layer, because Go's own type system is doing that job already.

## How a call actually flows: protocol, codec, registry, client plugin

rpcx uses a binary protocol that the README describes as platform-independent. A call moves through four separable layers, and each one is replaceable.

The transport layer carries the bytes. The core supports TCP and HTTP, with QUIC and KCP available behind build tags. The codec layer turns your Go values into bytes: JSON, Protobuf, MessagePack and raw byte slices are all listed as supported. The registry layer answers the question of which addresses are currently serving a given service name, with peer-to-peer, configured peers, ZooKeeper, etcd, Consul and mDNS all named in the README. The client plugin layer sits on top and decides behaviour: failover, failfast and failtry for fault tolerance; random, round robin, consistent hashing, weighted, network quality and geography for load balancing.

That separation is the design decision worth understanding before you commit. Because the layers are pluggable, you can change the registry without touching service code, or swap JSON for Protobuf without changing the method signatures. The same pluggability is why the registry clients no longer live in this repository. Since rpcx 1.7.6 the etcd, ZooKeeper, Consul and Redis plugins were moved to rpcx-etcd, rpcx-zookeeper, rpcx-consul and rpcx-redis respectively, and the InfluxDB and OpenTelemetry plugins moved to rpcx-plugins. The core module you install is therefore smaller than the framework you deploy.

## Installing smallnest/rpcx and making a first call

The README gives one install command for the base feature set. Run it inside a Go module; it pulls the framework and its dependencies into your module graph.

```bash
go get -v github.com/smallnest/rpcx/...
```

QUIC and KCP are not compiled in by default. They are gated behind build tags, and the README shows the combined form for a build that wants all of them.

```bash
go get -v -tags "quic kcp" github.com/smallnest/rpcx/...
```

The same tags apply to go build and go run, so a service that listens over QUIC needs the tag at compile time, not just at install time. The Makefile in the repository follows the same convention: its build-all target runs go build -tags "kcp quic" ./... and its test target runs go test -race -tags "kcp quic" ./... . If you build without the tags, the code paths that need them are not there.

For a registry, remember the split. The etcd plugin is not part of this module any more; it is a separate module at github.com/rpcxio/rpcx-etcd, and the same applies to rpcx-zookeeper, rpcx-consul and rpcx-redis. Add the one you actually run rather than assuming it arrived with the core install.

The go.mod in the repository declares go 1.26.0, so check your toolchain before you start. The README does not walk through a complete server and client pair, so the first real use is: register a struct with a server, point a client at an address or a registry, and call a method by name. If the call fails, the README points at rpcxdump, a tcpdump-like tool for debugging communication between rpcx services and clients.

## The plugin split is the upgrade cost you should price in

Moving etcd, ZooKeeper, Consul and Redis out of the core repository is a reasonable maintenance decision, and it has a direct consequence for anyone upgrading. A project that pinned one version of github.com/smallnest/rpcx and got its registry client along with it now tracks two release cadences. The core repository's recent releases are v1.9.0 in January 2025, v1.9.1 in August 2025 and v1.9.3 in April 2026. The registry plugins move on their own schedule, and a compatibility break between a core client interface and a plugin's implementation would surface as a build error in your module graph, not as a note in the core changelog.

The README also carries a branch-status line that deserves attention: the stable branch is listed as v1.7.x at the top of the document, while the announcement section says the stable branch is v1.9.4. Those two statements do not agree, and the releases list shows v1.9.3 as the most recent tagged release. If you are choosing a version to pin, resolve that contradiction against the repository's own branch list rather than trusting either line.

On maintenance: the repository is not archived, and the last push was on 2026-09-03, so there is current activity on master. That is a fact about the repository, not a promise about any particular plugin module, which you would need to check separately.

## Where rpcx is the wrong choice

The clearest boundary is cross-language contracts. rpcx's selling point, no proto files, is exactly what makes a Go struct a poor interface definition for a Python or Java consumer. The README does address this: rpcx-gateway lets clients in any language call rpcx services, HTTP invocation works through the same gateway, rpcx-java implements and accesses services over the raw protocol, and rpcx-rs lets you write services in Rust. But those are separate projects with their own maturity, and the core repository does not document their compatibility guarantees. If a non-Go client is a first-class requirement rather than a later addition, a schema-first framework gives you a contract both sides can generate from, and rpcx gives you a gateway.

The second boundary is operational surface. The feature list is long: circuit breaker, rate limiting, metrics, tracing, backup request, forking, broadcast, bidirectional communication, authorization, compression, heartbeat. Each is a plugin or an option, and each is something you configure and then debug. A team that wants one transport, one codec and a boring deployment is paying for flexibility it will not use.

The third is the documentation itself. The README is a feature list with a benchmark section, not a guide. It names capabilities and links to sibling repositories; it does not document rollback behaviour, version compatibility between core and plugins, or a migration path between releases. Expect to read the docs directory and the source.

## How rpcx differs from gRPC in approach

gRPC is the natural comparison, and the difference is not performance, it is where the contract lives. gRPC puts it in a .proto file, compiles that into stubs for every target language, and runs over HTTP/2. rpcx puts it in your Go method set and runs over its own binary protocol, with HTTP available as one transport among several.

That difference propagates. With gRPC, adding a field to a message is a schema change with defined compatibility rules, and the generated code is the same shape in Go, Java and Python. With rpcx, adding a method is a Go change, and every non-Go caller goes through rpcx-gateway or speaks the raw protocol. gRPC's HTTP/2 transport means ordinary proxies, load balancers and observability tools already understand the wire format. rpcx's binary protocol means you rely on the framework's own metrics, logging and tracing plugins, or on a tool like rpcxdump.

rpcx's counterargument is in the README's feature list: failover, failfast and failtry; consistent hashing and geography-aware balancing; backup request, forking and broadcast. Those are governance features that gRPC leaves to a service mesh or a separate control plane. If you want them inside the RPC library rather than beside it, that is the case for rpcx.

## Licence and what the repository states

The README carries an Apache 2.0 licence badge linking to opensource.org/licenses/Apache-2.0, and the repository has a LICENSE file at its top level. The metadata field for the repository reports NOASSERTION, which is a statement about automated licence detection, not about the project's intent. The practical reading is that the project presents itself as Apache 2.0 and ships a licence file; if you need certainty for a redistribution or a legal review, read that file rather than the badge.

Apache 2.0 carries an explicit patent grant and requires attribution and notice preservation. That is generally friendlier for commercial use than a copyleft licence, but it is not legal advice, and the plugin repositories under the rpcxio organisation are separate works whose licences you would check individually.

One dependency detail is worth flagging to whoever reviews the module graph: go.mod pulls in github.com/apache/thrift, github.com/quic-go/quic-go, github.com/redis/go-redis/v9 and github.com/smallnest/gordma, among others. The RDMA transport is described in the README as experimental and built on gordma's rdmanet.Conn, requiring libibverbs on Linux. An experimental transport with a system library dependency is not something to enable by default.

## Conclusion

Adopt rpcx if your services are written in Go, your team already runs etcd, Consul, ZooKeeper or mDNS, and you want to register ordinary Go methods rather than maintain proto files. Do not adopt it if your contract has to be language-neutral from day one, since the raw protocol path through rpcx-java or rpcx-rs is a separate project with its own pace, or if you need a single dependency tree that pins transports and registry clients together. Before writing service code, verify three things: that go.mod's go 1.26.0 directive is satisfied by your toolchain, that the registry plugin you intend to use lives in rpcx-etcd, rpcx-zookeeper, rpcx-consul or rpcx-redis rather than in the core module, and that you build with the tags your transport needs, since QUIC and KCP sit behind the quic and kcp build tags.

## FAQ

### Does smallnest/rpcx require proto files like gRPC?

No. The README states that rpcx supports raw Go functions and that there is no need to define proto files. You register a Go struct and its exported methods become callable services.

### How do I install smallnest/rpcx and enable QUIC or KCP?

The README gives go get -v github.com/smallnest/rpcx/... for the basic features, and go get -v -tags "quic kcp" github.com/smallnest/rpcx/... to include both transports. The same tags must be used with go build or go run.

### Where did the etcd, ZooKeeper, Consul and Redis plugins go?

Since rpcx 1.7.6 they were moved out of the core repository into independent projects: rpcx-etcd, rpcx-zookeeper, rpcx-consul and rpcx-redis. The InfluxDB and OpenTelemetry plugins moved to rpcx-plugins.

### Can I call a smallnest/rpcx service from Java, Rust or another language?

The README describes several routes: rpcx-gateway for clients in any language, HTTP invocation through that gateway, rpcx-java for services and clients over the raw protocol, and rpcx-rs for writing services in Rust. Those are separate projects, and the core repository does not document their compatibility guarantees.

## Sources

- [Issues](https://github.com/smallnest/rpcx/issues)
- [Project website](https://rpcx.io)
- [README](https://github.com/smallnest/rpcx/blob/master/README.md)
- [Releases](https://github.com/smallnest/rpcx/releases)
- [smallnest/rpcx on GitHub](https://github.com/smallnest/rpcx)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/smallnest-rpcx
