# TinyRPC: a teaching-first C++ coroutine RPC framework that says it is not production ready

> TinyRPC is a few thousand lines of C++11 built on coroutines and a reactor, supporting an HTTP(1.1) codec and a custom Protobuf-based binary protocol called TinyPB. Its own README states it is Linux-only, 64-bit only, and not of industrial strength, possibly with unknown bugs and coredumps.

**Gooddbird/tinyrpc** — c++ async rpc framework. 14w+qps.

- Repository: https://github.com/Gooddbird/tinyrpc
- Stars: 1,668 · Forks: 236
- Language: C++
- License: Apache-2.0
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/gooddbird-tinyrpc

## The README tells you not to use this in production

TinyRPC describes itself as a small asynchronous RPC framework built on the C++11 standard, with its core code on the order of a few thousand lines, kept deliberately concise and readable.

The framing is educational. The stated aim is to let a reader build a high-performance asynchronous RPC service quickly and lightly, and the README says at least a service built this way should cope with most current scenarios.

Then the constraints, stated without hedging. TinyRPC does not implement cross-platform support, supports only Linux, and requires a 64-bit system, because the coroutine switching code implements only the 64-bit case with no 32-bit compatibility. The reason given is that the author develops only on Linux and lacks the ability to make it cross-platform.

And the warning, which is the sentence that should decide your evaluation: the code has not reached industrial strength, should preferably not be used directly in a production environment, may contain unknown bugs, and may even coredump. Readers are asked to judge for themselves and use it cautiously.

The two core ideas are stated as a numbered list: make building a high-performance RPC service simple, and make asynchronous RPC calls simple.

The repository is small and matches the description: `tinyrpc/` for the library, `conf/` for configuration, `generator/` for the scaffolding tool, `testcases/`, plus `CMakeLists.txt`, `makefile`, `build.sh` and a `.devcontainer/` directory. Both a Makefile and CMake are supported, with install and uninstall targets for each.

The repository description also carries a throughput figure of 14w+ qps. That is the maintainer's own claim about the framework rather than a measurement you can rely on, and the README's performance section should be read as an illustration of the HTTP path rather than as a benchmark.

## Two protocols: HTTP(1.1) and a custom binary one

TinyRPC supports two wire protocols, and the choice determines whether you write a Servlet or a protobuf service.

The first is plain HTTP. The README says TinyRPC implements simple, quite basic HTTP(1.1) encoding and decoding, and that you can build an entire RPC service on the HTTP protocol. Building an HTTP service follows three documented steps: prepare a configuration file, implement a Servlet interface, and start the RPC server.

The second is TinyPB, described as a custom protocol based on Protobuf and belonging to the binary protocol family. Building a TinyPB service takes four steps: implement the protobuf file interface, prepare the configuration file, implement the business interface, and start the RPC server.

The design section breaks TinyPB down into a message format decomposition, so the framing is documented rather than opaque.

Both protocols sit on the same lower layers. The module list in the README's summary design section is: an asynchronous logging module, a coroutine module with coroutine encapsulation and an m:n thread-to-coroutine model, a Reactor module, a Tcp module split into `TcpServer` and `TcpConnection`, the TinyPB protocol, the Http module, and the RPC call wrapper.

There is also an error code section with two parts, a specification for how error codes should be judged and a document explaining their meanings. That is worth noticing: a framework that defines how a caller should interpret a failure is making a statement about error handling as part of its API rather than leaving it to string matching.

The m:n model is the load-bearing decision. Coroutines are scheduled onto a pool, so the number of OS threads doing IO is decoupled from the number of concurrent calls.

## Two call styles, and the recommended one blocks the coroutine

The README calls the recommended call style 阻塞协程式异步调用, literally blocking-coroutine asynchronous call, and flags the name as confusing before explaining why it is efficient. The idea is written as achieving asynchronous performance with synchronous code. You call a function directly, there is no callback to write, and the coroutine encapsulation inside makes it genuinely asynchronous while the caller stays unaware.

The corresponding class is `TinyPbRpcChannel`:

```c++
tinyrpc::TinyPbRpcChannel channel(std::make_shared<tinyrpc::IPAddress>("127.0.0.1", 39999));
QueryService_Stub stub(&channel);

tinyrpc::TinyPbRpcController rpc_controller;
rpc_controller.SetTimeout(10000);

DebugLog << "RootHttpServlet begin to call RPC" << count;
stub.query_name(&rpc_controller, &rpc_req, &rpc_res, NULL);
DebugLog << "RootHttpServlet end to call RPC" << count;
```

The README explains that the `stub.query_name` line is in effect fully asynchronous: the thread does not block there and goes off to handle other coroutines, and `query_name` returns only when the data is ready. During the interval between the call and its return, control has been handed to the main coroutine, which can respond to client requests, run timed tasks, or sit in `epoll_wait`. The individual coroutine is blocked; the thread is not.

The stated advantages are three: the code is simple and synchronous with no callbacks, there is no limit on the number of IO threads and the effect still works with only one IO thread, and the thread itself never blocks. The stated disadvantage is equally direct: the current coroutine is blocked and must wait to be resumed before continuing.

The non-blocking variant is `TinyPbRpcAsyncChannel`, compared in the README to C++11 futures but not quite the same. The call returns immediately and the calling coroutine continues, and the README notes this does not mean the RPC completed.

```c++
async_channel->saveCallee(rpc_controller, rpc_req, rpc_res, nullptr);

QueryService_Stub stub(async_channel.get());
stub.query_age(rpc_controller.get(), rpc_req.get(), rpc_res.get(), NULL);
```

If you want the result, you call `async_channel->wait()`, which blocks the current coroutine until the call completes while leaving the thread free, in effect yielding the coroutine and resuming it when the response arrives. `wait()` is optional: skip it and the call behaves as an asynchronous task queue.

The cost is a memory rule. All objects involved in the call must be heap objects rather than stack objects, including req, res, controller and the async channel, and `shared_ptr` is strongly recommended because otherwise there may be unexpected problems. `saveCallee` must be called before the RPC to reserve the resource reference counts in advance, which the README describes as effectively a supplement to the first rule and close to a mandatory `shared_ptr` requirement.

## Building it: dependencies, then Makefile or CMake

Installation has two named dependencies and two build paths.

The dependencies are protobuf and tinyxml, each with its own subsection in the README. Protobuf is needed because TinyPB is built on it, and the generator reads your `.proto` files.

Both build systems offer install and uninstall targets, so `make install` and the CMake equivalent are documented side by side. A `build.sh` at the root suggests a scripted path as well, and `.devcontainer/` means a development container is available for working on it.

Configuration is file-based under `conf/`, and the two tutorials each start with a step called preparing the configuration file, which tells you the server's settings are not compiled in.

The scaffolding tool is `tinyrpc_generator`, and its documentation is the most substantial part of the quick-start section. You prepare a protobuf file, generate the TinyRPC framework code, then write your business logic against what was generated.

Two generator subsections matter for maintenance. One is titled asking what to do when the protobuf interface is upgraded, which in practice is the question everyone asks about any generated RPC layer. The other is an options reference for `tinyrpc_generator`.

The performance section is a single subsection, an HTTP echo QPS test. Reading it as context rather than as evidence: an echo endpoint is the shortest possible path through the framework and its throughput reflects the framework's overhead, not the performance of any service you would build on it.

## Where TinyRPC is the wrong tool

The mismatches are mostly consequences of the stated design goals rather than oversights.

It is Linux-only and 64-bit-only. A team that develops on macOS and deploys on Linux has no development environment here, and a 32-bit target is out.

It is not production ready by the author's own statement, and the warning names coredumps. That is disqualifying for anything with an availability requirement.

The protocol support is thin. HTTP(1.1) is described as simple and basic, and TinyPB is a custom binary format you would have to interoperate with from other languages yourself, since the README documents generation from protobuf for this framework's own stubs and nothing about a cross-language client.

The non-blocking call style's heap-allocation requirement is a real ergonomic cost. Stack-allocated req and res objects are what most C++ programmers write first, and the framework will not accept them.

A production-oriented alternative may suit deployment requirements that TinyRPC does not address. TinyRPC instead optimises for the readability of a few thousand lines of core C++11 code built around a reactor, epoll and an m:n coroutine scheduler.

If the reason you are considering TinyRPC is that you want to understand how a coroutine RPC framework works, reading it beats configuring one. If the reason is throughput on a production service, the README's own advice applies.

## Conclusion

Adopt TinyRPC if you are learning asynchronous RPC in C++ on Linux, because the README's stated purpose is to let readers build a high-performance asynchronous RPC service quickly and lightly, and a codebase you can read end to end serves that better than a production library would. Do not adopt it in production: the README says plainly that the code has not reached industrial strength, recommends against using it in production, and warns of unknown bugs and possible coredumps. Verify three things before you build anything on it: that you are on a 64-bit Linux system, because the coroutine switch is implemented only for 64-bit with no 32-bit compatibility and this is described as deliberate; that you have the two named dependencies, protobuf and tinyxml; and that you can accept the generator dependency, since `tinyrpc_generator` scaffolds code from your protobuf file and the README documents how to handle a protobuf interface upgrade. The license is Apache-2.0. The last push was on 2026-08-12, while the most recent tagged release is v1.2.0 from 2022-11-05, so read the source rather than the tag if you want current behaviour.

## FAQ

### Is TinyRPC safe for production use?

No. The README states the code has not reached industrial strength, that it should preferably not be used directly in a production environment, and that it may contain unknown bugs and even coredump.

### Which platforms does TinyRPC support?

Linux only, and 64-bit systems only, because the coroutine switching is implemented only for 64-bit with no 32-bit compatibility. The README says this is deliberate, since the author develops only on Linux.

### What protocols does TinyRPC support?

Two: a basic HTTP(1.1) codec for building an RPC service over HTTP, and TinyPB, a custom binary protocol based on Protobuf. HTTP services implement a Servlet interface while TinyPB services implement a protobuf service interface.

### What is the difference between blocking and non-blocking coroutine RPC calls in TinyRPC?

The blocking coroutine style through TinyPbRpcChannel looks synchronous with no callbacks, and the thread is never blocked, though the current coroutine waits to be resumed. The non-blocking style through TinyPbRpcAsyncChannel returns immediately and you optionally call wait() for the result, but every related object must be heap allocated with shared_ptr and saveCallee must be called first.

### What dependencies does TinyRPC need to build?

protobuf and tinyxml. Both a Makefile and CMake are provided, each with install and uninstall targets, and there is also a build.sh script and a .devcontainer directory.

### What license is TinyRPC released under?

Apache-2.0, with the LICENSE file at the repository root. The most recent tagged release is v1.2.0 from 2022-11-05, while the last push was on 2026-08-12.

## Sources

- [Gooddbird/tinyrpc on GitHub](https://github.com/Gooddbird/tinyrpc)
- [Issues](https://github.com/Gooddbird/tinyrpc/issues)
- [License: Apache-2.0](https://github.com/Gooddbird/tinyrpc/blob/main/LICENSE)
- [README](https://github.com/Gooddbird/tinyrpc/blob/main/README.md)
- [Releases](https://github.com/Gooddbird/tinyrpc/releases)

---

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