Load-Balance C++ Connections to YugabyteDB (YSQL via libpq)

Yugabyte’s Smart Drivers (Java, Python, Go, etc.) handle load balancing, leader routing, etc.

C++, however, doesn’t yet have that…

But we can use libpq (PostgreSQL C client) to distribute connections across multiple hosts with minimal effort, starting from PostgreSQL client 16+, via load_balance_hosts=random. And because YSQL is wire-compatible with PostgreSQL, this just works with YugabyteDB. Let’s see how.

Install Prereqs
  • g++ (C++ compiler)

  • libpq (PostgreSQL client libraries v16+)

  • libpqxx (C++ wrapper for libpq)

Ubuntu / Debian
				
					sudo apt update
sudo apt install -y g++ libpq-dev libpqxx-dev
pg_config --version   # should say 16.x or newer
				
			
macOS (Homebrew)
				
					brew install libpq libpqxx
echo 'export PATH="/opt/homebrew/opt/libpq/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
pg_config --version
				
			
AlmaLinux / RHEL 9
				
					# Enable PostgreSQL 16 repo
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

# Install base deps
sudo dnf install -y gcc-c++ make pkg-config

# Install libpq 16 and headers
sudo dnf install -y postgresql16-devel

# libpqxx (C++ wrapper)
sudo dnf install -y libpqxx-devel || {
  echo "If not available, enable EPEL or build libpqxx from source:"
  echo "  sudo dnf install -y epel-release && sudo dnf install -y libpqxx-devel"
}

# Verify
/usr/pgsql-16/bin/pg_config --version

				
			
Quick Cluster Check
				
					for H in 127.0.0.1 127.0.0.2 127.0.0.3; do
  PGPASSWORD=yugabyte ysqlsh "host=$H port=5433 dbname=yugabyte user=yugabyte" \
    -c "SELECT split_part(version(), '-', 3) yb_version, inet_server_addr();"
done
				
			

Example:

				
					[root@localhost ~]# for H in 127.0.0.1 127.0.0.2 127.0.0.3; do
  PGPASSWORD=yugabyte ysqlsh "host=$H port=5433 dbname=yugabyte user=yugabyte" \
    -c "SELECT split_part(version(), '-', 3) yb_version, inet_server_addr();"
done
 yb_version | inet_server_addr
------------+------------------
 2025.1.0.0 | 127.0.0.1
(1 row)

 yb_version | inet_server_addr
------------+------------------
 2025.1.0.0 | 127.0.0.2
(1 row)

 yb_version | inet_server_addr
------------+------------------
 2025.1.0.0 | 127.0.0.3
(1 row)
				
			

Create a simple table to query later:

				
					PGPASSWORD=yugabyte ysqlsh \
  "host=127.0.0.1 port=5433 dbname=yugabyte user=yugabyte" \
  -c "CREATE TABLE IF NOT EXISTS lb_demo(id INT PRIMARY KEY, note TEXT);
      INSERT INTO lb_demo VALUES (1, 'Hello from YB!');"
				
			
Minimal C++ Program

Save as yb_lb_demo.cpp:

				
					#include <iostream>
#include <pqxx/pqxx>

int main() {
  const std::string conninfo =
    "host=127.0.0.1,127.0.0.2,127.0.0.3 "
    "port=5433 dbname=yugabyte user=yugabyte password=yugabyte "
    "sslmode=disable load_balance_hosts=random target_session_attrs=any";

  try {
    pqxx::connection c{conninfo};
    pqxx::work tx{c};
    auto r = tx.exec(
      "SELECT inet_server_addr()::TEXT AS server_ip, inet_server_port() AS server_port, "
      "(SELECT note FROM lb_demo WHERE id = 1) AS note");
    tx.commit();

    std::cout << "Connected to: "
              << r[0]["server_ip"].c_str() << ":" << r[0]["server_port"].as<int>()
              << " | note=" << r[0]["note"].c_str() << "\n";
  } catch (const std::exception &e) {
    std::cerr << "Error: " << e.what() << "\n";
    return 1;
  }
  return 0;
}
				
			

Build it:

				
					g++ -std=c++17 yb_lb_demo.cpp $(pkg-config --cflags --libs libpqxx) -o yb_lb_demo
				
			
Run It
				
					for i in {1..12}; do ./yb_lb_demo; done
				
			

Example:

				
					[root@localhost ~]# for i in {1..12}; do ./yb_lb_demo; done
Connected to: 127.0.0.1/32:5433 | note=Hello from YB!
Connected to: 127.0.0.3/32:5433 | note=Hello from YB!
Connected to: 127.0.0.3/32:5433 | note=Hello from YB!
Connected to: 127.0.0.2/32:5433 | note=Hello from YB!
Connected to: 127.0.0.2/32:5433 | note=Hello from YB!
Connected to: 127.0.0.1/32:5433 | note=Hello from YB!
Connected to: 127.0.0.2/32:5433 | note=Hello from YB!
Connected to: 127.0.0.2/32:5433 | note=Hello from YB!
Connected to: 127.0.0.1/32:5433 | note=Hello from YB!
Connected to: 127.0.0.3/32:5433 | note=Hello from YB!
Connected to: 127.0.0.2/32:5433 | note=Hello from YB!
Connected to: 127.0.0.2/32:5433 | note=Hello from YB!
				
			

Each run shows a different IP, connections are load balanced across your cluster.

Why It Matters
  • ✅ Uses stock PostgreSQL client libs

  • ✅ Works with YugabyteDB’s PostgreSQL-compatible YSQL API

  • ✅ Balances connections across nodes

  • ✅ Perfect for apps with connection pooling

Wrap-Up

Even without a dedicated Smart Driver for C++, you can still achieve simple, effective connection load balancing against a YugabyteDB cluster using libpq v16+ and libpqxx.

Have Fun!

I love catching horror flicks solo at the local Cinemark. Yesterday I went to see "Weapons" and spotted this Annabelle popcorn bucket at the counter… even I thought it was a little too creepy!