# userver: an asynchronous C++ framework for microservices that never block a thread

> userver is an Apache-2.0 C++20 framework whose core promise is that I/O operations do not suspend the calling thread. Here is what the repository actually documents, how to build the hello_service sample, and where the framework is the wrong choice.

**userver-framework/userver** — Production-ready C++ Asynchronous Framework with rich functionality

- Repository: https://github.com/userver-framework/userver
- Website: https://userver.tech
- Stars: 2,978 · Forks: 407
- Language: C++
- License: Apache-2.0
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/userver-framework-userver

## The problem userver solves: I/O that suspends the thread

The README states the problem in one sentence: operations that would typically suspend the thread of execution do not suspend it. Instead, the thread processes other requests and tasks and returns to the operation only when it is guaranteed to execute immediately. That is a different bargain from the usual thread-per-request server. In a blocking model, a query to PostgreSQL parks an OS thread until the socket becomes readable, and the process pays for context switches and stack memory per connection. userver keeps a small number of execution threads and multiplexes the waiting.

The intended audience is narrow and specific: teams writing C++ microservices, services and utilities where most of the work is network and database round trips. The README describes the project as an open source asynchronous framework with a rich set of abstractions for fast and comfortable creation of C++ microservices, services and utilities. It is not a general purpose library, and it is not a GUI toolkit or a compute kernel. If your hot path is matrix multiplication, the asynchronous machinery buys you nothing.

The repository topics line up with that positioning: async, coroutines, cplusplus-20, grpc, http, microservices, postgres, redis. The framework is licensed Apache-2.0, which matters if you ship a proprietary binary and want an explicit patent grant. That is a licence fact, not legal advice; read the LICENSE file yourself.

## How the asynchronous core works, and what the easy::HttpWith example shows

The README's example is the clearest statement of the data flow. It uses the easy::HttpWith<easy::PgDep> helper, which wires an HTTP server and a PostgreSQL dependency together from argc/argv. The handler is registered on the /kv URL and takes a parsed request plus the dependency. Inside the handler, dep.pg().Execute runs the SQL against ClusterHostType::kSlave. The comment in the example says the current thread handles other requests while the response from the DB is being received.

Two details in that snippet are worth reading twice. First, the query is converted into a prepared statement, so subsequent requests send only parameters in binary form and the database discards the meta information. Second, the request and response types (schemas::KeyRequest, schemas::KeyValue) come from a JSON schema, with parsers and serializers generated from it. That generation step is a build-time concern, not a runtime reflection trick.

Below the easy layer, the README lists what the framework provides: asynchronous drivers for MongoDB, PostgreSQL, Valkey, Redis, ClickHouse, MySQL/MariaDB, YDB and SQLite; protocols including HTTP/1.1, HTTP/2.0, gRPC, AMQP 0-9-1, Kafka, TCP, TLS and WebSocket; plus components for caches, tasks, distributed locking, logging, tracing, statistics and metrics, and JSON/YAML/BSON handling. Configuration can be changed on the fly, and the drivers, deadline propagation, timeouts and congestion control are described as configurable at runtime. The top-level repository directories mirror the driver list: postgresql/, mongo/, redis/, kafka/, grpc/, clickhouse/, mysql/, ydb/, sqlite/, rabbitmq/, scylla/, odbc/.

The design cost is real. Asynchronous code in C++ usually means callbacks or coroutines, and the framework commits to C++20 coroutines as one of its topics. Debugging a suspended coroutine is harder than reading a stack trace from a blocked thread, and the README does not claim otherwise.

## Getting started: building userver and running the hello_service sample

The repository is built with CMake, and the Makefile gives the canonical entry points. The debug configuration is created with cmake -B build_debug and the debug flags default to -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON, with sanitizers enabled through -DUSERVER_SANITIZE=addr;ub. The release configuration uses -DCMAKE_BUILD_TYPE=Release. You can override the flags in a Makefile.local file, which the Makefile includes if present.

```bash
cmake -B build_release -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
cmake --build build_release -j $(nproc)
```

The first command configures the release build and writes compile_commands.json for clangd or any tool that consumes it. The second compiles the tree with one job per core. Expect this to take a while on a first run; the framework covers many drivers and protocols, and the Makefile's test target raises the file descriptor limit with ulimit -n 4096 before invoking ctest, which tells you the test suite opens many sockets.

The samples/ directory is where a first real use lives. It contains hello_service, config_service, grpc_service, mongo_service, kafka_service, postgresql-adjacent samples, https_service, http_caching, cors_service, digest_auth_service and others. The README does not spell out a per-sample build invocation, so the honest instruction is: read samples/README.md and samples/CMakeLists.txt, then build the sample target you want from your configured build directory. The Makefile also exposes a docs target that runs ./scripts/docs/make_docs.sh, which is how the project generates the documentation site at userver.tech.

For a first experiment, hello_service is the smallest surface: it exercises the HTTP server and the component system without requiring a database. Move to the PostgreSQL sample only after the toolchain is proven, because that sample needs a reachable database.

## Build weight, platform coverage and the C++20 requirement

The README's badge list is effectively the platform support statement: CI workflows exist for Ubuntu, Fedora, Debian, macOS, Alpine and Arch, plus Docker CI and Conan CI. There are also published container images for ubuntu-24.04 and ubuntu-22.04, and a separate userver-overlay repository with a Gentoo systemd workflow. If your target is a Linux distribution outside that set, you are on your own for the dependency graph.

C++20 is not optional. The topics include cplusplus-20 and cpp20, and the framework's coroutine support depends on it. A codebase still on C++17 cannot adopt userver incrementally without a language-standard migration first. That is a hard boundary, not a configuration flag.

The build is not lightweight. A CMake configure of this tree reaches into third_party/ and the many top-level driver directories, and the Makefile's dist-clean target hints at the artifacts involved: build_*/ folders, debian/, .ruff_cache/, _CPack_Packages/, .mypy_cache and __pycache__. The presence of pyproject.toml, pytest.ini and a testsuite/ directory means a meaningful part of the test infrastructure is Python, so a C++-only CI image will not run the full suite. Budget for that before you promise a build in a minimal container.

The repository also ships AGENTS.md and CLAUDE.md at the top level. Those are instructions for AI coding agents working in the repository, not user documentation; do not mistake them for a getting-started guide.

## Where userver is the wrong tool, and what to use instead

If you need one HTTP endpoint that calls one database and you measure the project in hundreds of lines, the framework's component model, configuration system and generated schema types are overhead. A blocking server with a thread pool will be easier to reason about, and at low concurrency the difference in throughput will not pay for the learning curve. The README itself frames the benefit as efficient utilization of the CPU with a small amount of execution threads, which is a claim about scale, not about small services.

The closest alternative in the same space is Boost.Asio. The difference in approach is structural rather than cosmetic. Asio gives you an executor, sockets and timers, and leaves the service architecture to you: connection pooling, configuration reload, metrics, tracing and database drivers are your problem or someone else's library. userver ships those as framework components with on-the-fly configuration and deadline propagation built in. You trade control over the event loop for a batteries-included service skeleton, and you accept the framework's opinions about how a service is assembled.

A second alternative, for teams already invested in the Go or Java ecosystems, is to not use C++ at all. The README does not argue against that; it presents userver as a way to get asynchronous I/O in C++ specifically. If the language choice is not fixed, the framework's advantages do not transfer.

The wrong-tool case also includes anything that cannot tolerate a large dependency tree: embedded targets, minimal static binaries, and environments where every third-party library needs a security review. The driver list that makes userver attractive is the same list that expands your supply chain.

## Maintenance cadence, release history and upgrade cost

The repository is not archived, and the last push was on 2026-09-23. The recent release tags are v3.2 on 2026-09-09, v3.1 on 2026-06-30 and v3.0 on 2026-04-16. That is a release roughly every two to three months across the 3.x line, with the default branch named develop. If you track develop you are tracking a moving branch; if you pin a tag you get a stable point but you take on the cost of jumping between releases.

The upgrade cost is dominated by the framework's breadth. A version bump can touch the build system, the generated schema code, the component configuration and the driver APIs at once. The repository carries a version.txt file at the top level, which is the machine-readable version marker, and the Makefile's docs and docs-upload targets regenerate the documentation site from the same tree, so documentation and code move together.

On licensing: the project is Apache-2.0, which permits commercial and closed-source use and includes an explicit patent grant. The repository also has a THIRD_PARTY.md file, which is where the dependency licences are recorded. If your legal review requires a full dependency inventory, that file is the starting point, and the many top-level driver directories are the reason it exists. Nothing here is legal advice; have counsel read LICENSE and THIRD_PARTY.md.

The README does not document a rollback procedure or a compatibility policy between major versions. If downgrading matters to your deployment, that gap is something you will have to fill yourself.

## Conclusion

Adopt userver if you are building a C++ service that is dominated by I/O against PostgreSQL, MongoDB, Redis, Kafka or gRPC, and you are willing to accept a CMake build that pulls a large dependency tree. Do not adopt it for a short-lived command line tool, a GUI, or a codebase that cannot move to C++20. Before committing, verify three things on your own machine: that the toolchain in your CI matches the platform workflows listed in the README, that the driver you need exists under the top-level directory for it (postgresql/, mongo/, redis/, kafka/, grpc/), and that the samples/hello_service target builds and runs in your environment. The framework is developed on the develop branch, with v3.2 released on 2026-09-09 and the last push on 2026-09-23.

## FAQ

### What is userver used for?

It is an open source asynchronous framework for building C++ microservices, services and utilities. The README describes it as solving efficient I/O interactions transparently, so operations that would suspend a thread do not suspend it.

### Which C++ standard does userver require?

The repository topics include cplusplus-20 and cpp20, and the framework's coroutine support depends on that standard. A codebase on C++17 cannot adopt it without a language-standard migration first.

### Which databases and protocols does userver support?

The README lists asynchronous drivers for MongoDB, PostgreSQL, Valkey, Redis, ClickHouse, MySQL/MariaDB, YDB and SQLite, and protocols including HTTP/1.1, HTTP/2.0, gRPC, AMQP 0-9-1, Kafka, TCP, TLS and WebSocket. The top-level repository directories mirror that list.

### How do I build userver from source?

The Makefile configures with cmake -B build_release -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON and builds with cmake --build build_release. The debug configuration adds -DUSERVER_SANITIZE=addr;ub, and flags can be overridden in a Makefile.local file.

### Is userver maintained?

The repository is not archived and the last push was on 2026-09-23, with v3.2 released on 2026-09-09. Development happens on the develop branch.

## Sources

- [License: Apache-2.0](https://github.com/userver-framework/userver/blob/develop/LICENSE)
- [Project website](https://userver.tech)
- [README](https://github.com/userver-framework/userver/blob/develop/README.md)
- [Releases](https://github.com/userver-framework/userver/releases)
- [userver-framework/userver on GitHub](https://github.com/userver-framework/userver)

---

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