pgagroal, a protocol-native connection pool for PostgreSQL
High-performance connection pool for PostgreSQL
At a glance
- What is it?
- pgagroal/pgagroal sits between an application and PostgreSQL speaking the native v3 protocol over liburing, with a shared memory model across processes, per user and database connection limits, TLS, Prometheus metrics and a user vault. It is written in C, BSD licensed, and tested on the main Linux distributions plus FreeBSD and OpenBSD.
- Who is it for?
- Adopt pgagroal if you run a service that opens and closes PostgreSQL connections faster than the server likes, and you want pooling with per user and database limits rather than a proxy that speaks a different protocol. Skip it if your bottleneck is query time rather than connection overhead, since a pool will not help there, or if you need multi-master failover with automatic routing, which is not what it does.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 22 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What protocol-native means and why it is the point
pgagroal is described as a high-performance protocol-native connection pool for PostgreSQL. The name of the project comes from a place in Portugal, a beach and river area called Agroal, and the project spells out the pronunciation.
The important word in that description is native. Most connection proxies for PostgreSQL, PgBouncer being the famous one, speak a simplified subset of the protocol and terminate the client connection, then re-establish a server connection. That works, but it means the proxy has to parse and re-emit the protocol messages, and some things break: session-level state, prepared statement behaviour, and anything relying on features the proxy does not implement.
pgagroal speaks the PostgreSQL native protocol version 3 directly. The README says it will work with any PostgreSQL compliant driver, naming pgjdbc, Npgsql and pq. So an application changes its connection string and nothing else about its driver behaviour.
The rest of the implementation choices follow the same logic. It uses a process model with a shared memory model across processes, so the worker processes that handle connections do not need to pass state through pipes or locks. liburing provides the fast network interactions, and atomic operations keep track of state.
The practical summary is that this is a pool that gets out of the way of the protocol rather than a proxy that interprets it.
The feature list read as a set of operational controls
The features in the README group into three kinds of thing.
The first group is connection lifecycle control. Beyond pooling itself there is prefill support, which pre-creates connections so the first requests do not pay for the handshake. There is removal of idle connections, so the pool does not hold open connections nothing is using. There is connection validation, which checks that a pooled connection is still good before handing it out, and graceful or fast shutdown, so the pool can be stopped without dropping work in progress.
The second group is access control. You can limit connections for users and for databases separately, and you can enable or disable database access outright. There is authentication query support, which is how the pool checks credentials against a query you define rather than against a static list, and a user vault, which is the pool's own credential store for the server side.
The third group is operational plumbing. Prometheus support with a Grafana 12 dashboard gives you the metrics to see what the pool is doing. Remote management means the pool can be inspected and adjusted without restarting it. Transport Layer Security version 1.2 and above is supported, which matters if the pool sits between zones. Daemon mode lets it run in the background rather than in the foreground of a terminal. And failover support is listed among the features.
Two of the supporting documents in the repository are worth knowing about before evaluating it. The getting started guide covers installation, the configuration document covers the settings, and the performance document covers a performance run, with the architecture document describing the design in more detail.
Building from source on Linux
The dependency list is what tells you this is a native Linux tool rather than a portable one. It needs gcc 8 or newer with C17 support or clang 8 or newer, cmake, GNU make or BSD make, liburing, OpenSSL, libatomic, and a documentation toolchain including rst2man, Doxygen and xelatex. On Linux it also needs systemd, and it wants zlib, zstd, lz4 and bzip2.
On Fedora the README gives the whole list in one command:
dnf install git gcc cmake make \
liburing liburing-devel \
openssl openssl-devel \
systemd systemd-devel \
python3-docutils \
libatomic \
zlib zlib-devel \
libzstd libzstd-devel \
lz4 lz4-devel \
bzip2 bzip2-devel \
clang clang-analyzer clang-tools-extraThe release build is a standard out-of-source CMake build followed by an install into a prefix:
git clone https://github.com/pgagroal/pgagroal.git
cd pgagroal
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr/local ..
make
sudo make install
/usr/local/bin/pgagroal -c /usr/local/etc/pgagroal/pgagroal.conf -a /usr/local/etc/pgagroal/pgagroal_hba.confThe final line matters. The daemon is started with two configuration files: the main configuration and a host based authentication file, in the pgagroal_hba.conf style borrowed from PostgreSQL's own pg_hba.conf. That second file is where you decide which clients may connect.
The debug build differs only in the cmake flag and in where you run it from:
git clone https://github.com/pgagroal/pgagroal.git
cd pgagroal
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Debug ..
make
cd src
cp ../../doc/etc/*.conf .
./pgagroal -c pgagroal.conf -a pgagroal_hba.confThe README notes you have to set the log_level configuration option to debug5 for the debug build to be useful, which is the sort of detail that saves an afternoon.
There is also a spec file in the repository, pgagroal.spec, and the RPM document explains how to build a package from it.
Platforms, releases and where a pool actually helps
The tested platforms are Fedora 38 and later, RHEL 9.x, Rocky Linux 9.x, FreeBSD and OpenBSD. The presence of liburing in the required dependencies means the fast network path is Linux-specific in practice, since io_uring is a Linux kernel feature, even though the project also builds and is tested on the BSDs.
The release history shows steady work with a recent major version: 2.0.1 in February 2026, 2.0.2 later the same month, and 2.1.0 in April 2026. The last push was on 2026-10-01.
Now the question that actually matters for an adoption decision, which is when a connection pool earns its place. The classic case is an application that opens a connection per request or per user action, so connection establishment dominates the latency and the server runs out of max_connections. A pool fixes that directly.
The second case is an environment where the server and the client are far apart, so the handshake is expensive over a high latency link. Pooling with prefill amortises that.
The third is isolation. If your application has many end users who each need their own database session, a pool with per user limits can enforce a cap on how many sessions any one user holds, which protects the server from a single noisy tenant.
What a pool does not fix is slow queries. If your latency is in the query itself, pooling changes nothing, and adding a proxy in the path adds a hop and a failure mode. That is the main reason to measure before deploying one, and the README points at a performance document for a reference run.
How it compares with PgBouncer and with an application-level pool
PgBouncer is the comparison that has to be made, because it is the dominant option in this space. The difference in approach is the protocol handling.
PgBouncer implements its own simplified protocol handling and terminates the client session, which means the pooler decides what a session is and clients connect to a pool rather than to a database. It has been the default answer for years and it is fast.
pgagroal takes the opposite approach and speaks the full native protocol, keeping a real PostgreSQL session behind each pooled connection. The advantage is fidelity: features that depend on session state survive, and the pool does not have to approximate the protocol. The cost is that pgagroal is a newer project with a smaller track record, and its own feature set, such as the user vault and the remote management surface, is a smaller set of proven components.
The second alternative is pooling inside the application, in the driver or in the connection library. This is the default for many frameworks and it has real advantages: no extra network hop, no separate process to operate, and the pool lives in the same failure domain as the application. The disadvantages are that each application needs its own pool, so the total connection count across a fleet is the sum of all the pools, and a limit enforced per process is not a limit enforced across the estate. A server-side pool gives you one place to set and observe the cap.
There is also the option of doing nothing and tuning PostgreSQL. If the connection churn is modest, raising max_connections and accepting the per-connection memory cost is simpler than running a proxy. The pool earns its place when connection establishment is genuinely the bottleneck, and the performance document in the repository is where you would check that.
Editorial conclusion
Adopt pgagroal if you run a service that opens and closes PostgreSQL connections faster than the server likes, and you want pooling with per user and database limits rather than a proxy that speaks a different protocol. Skip it if your bottleneck is query time rather than connection overhead, since a pool will not help there, or if you need multi-master failover with automatic routing, which is not what it does. Verify first by building the release target with cmake and make, then check that your driver works against the pool with the PostgreSQL native protocol, and set log_level to debug5 before you trust the metrics.
Frequently asked questions
What is pgagroal and what makes it protocol-native?
pgagroal is a high-performance connection pool for PostgreSQL written in C that speaks the PostgreSQL native protocol version 3 directly, using liburing for network interaction and a shared memory model across its worker processes. It works with any PostgreSQL compliant driver such as pgjdbc, Npgsql or pq.
How do I build pgagroal from source?
Clone the repository, create a build directory, run cmake with an install prefix, then make and sudo make install. You need gcc 8 or newer with C17, cmake, liburing, OpenSSL, libatomic and systemd on Linux, and the full dependency list is given in the README.
Which configuration files does pgagroal need at startup?
Two. The main configuration, passed with -c, and a host based authentication file, passed with -a, in the style of PostgreSQL's own pg_hba.conf. The README shows both under /usr/local/etc/pgagroal/ after installation.
What are pgagroal's main operational features?
Prefill support, removal of idle connections, connection validation, graceful or fast shutdown, limits on connections per user and per database, enabling or disabling database access, authentication query support, a user vault, remote management, Prometheus metrics with a Grafana 12 dashboard, TLS 1.2 and above support, and daemon mode.
How does pgagroal differ from PgBouncer?
PgBouncer terminates the client session and implements its own simplified protocol handling, while pgagroal keeps a real PostgreSQL session behind each pooled connection and speaks the native v3 protocol. pgagroal is a newer project with a smaller track record, but with higher protocol fidelity.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pgagroal-pgagroal)Was this useful?