Skip to main content
pgAgroal Enterprise docs · Migrate from PgBouncer

pgAgroal Enterprise · How-to

Migrate from PgBouncer

Replacing PgBouncer is a practical blocker for many teams: you already have a pgbouncer.ini with routing and auth assumptions to understand before you can move. The Enterprise pgbouncer-import tool converts that configuration into pgagroal config and produces a human-readable migration report — so the move is a reviewed translation, not a guess.

What the tool does

pgbouncer-import reads a pgbouncer.ini and writes two things: a translated pgagroal.conf and a migration report. It never silently drops or guesses settings.

  • Translates the safe [pgbouncer] keys into pgagroal configuration.
  • Maps compatible pool modes to pgagroal pipeline behaviour.
  • Parses [databases] entries and reports the routing implications.
  • Reports unsupported keys explicitly, so you decide rather than the tool guessing.
  • Requires no change to pgagroal itself.

Convert your config

Point the tool at your pgbouncer.ini, writing the config and report to files:

pgbouncer-import -o pgagroal.conf -report migration-report.txt pgbouncer.ini

With no -o the config goes to stdout; with no -report the report goes to stderr. Pass - as the path to read from stdin, which is handy in a pipeline:

cat /etc/pgbouncer/pgbouncer.ini | pgbouncer-import - > pgagroal.conf

Review the migration report

Read the report before deploying. It lists what was translated, what needs a manual decision, and the backend/database routing it derived. Anything the report flags as unsupported is a deliberate prompt for you to choose an equivalent in pgagroal rather than an assumption baked into the output.

The report is the deliverable to review with whoever owns your current PgBouncer routing and auth — treat the generated pgagroal.conf as a reviewed starting point, not a drop-in replacement.

Worked example

This shows a small pgbouncer.ini, the pgagroal.conf the tool writes from it, and the part of the report that asks you to decide something. Map the shape onto your own file rather than the exact values.

Input: pgbouncer.ini

PgBouncer keeps its settings in an INI file. The [databases] block lists which database each client name routes to; the [pgbouncer] block holds pooler settings.

[databases]
appdb = host=db1.internal port=5432 dbname=appdb

[pgbouncer]
listen_port = 6432
max_client_conn = 500
pool_mode = transaction
default_pool_size = 20
so_reuseport = 1

Output: pgagroal.conf

The tool writes a [pgagroal]section (the pooler’s own settings) and a derived [primary] backend (where the pooler connects upstream, taken from the [databases] entry).

[pgagroal]
port = 6432
max_connections = 500
pipeline = transaction
# (other pgagroal defaults omitted)

[primary]
host = db1.internal
port = 5432
  • listen_port = 6432 becomes port = 6432 in [pgagroal].
  • max_client_conn = 500 becomes max_connections = 500.
  • pool_mode = transaction becomes pipeline = transaction (and pool_mode = session becomes pipeline = session).
  • The appdb line in [databases] becomes the derived [primary] backend with host = db1.internal.

Migration report excerpt

The report is plain text. Its exact layout may differ, but it conveys what was translated, the backend it derived, and what it could not translate — the last group is a list of decisions for you, not settings the tool silently dropped:

Translated:
  listen_port = 6432       ->  [pgagroal] port = 6432

Derived backend:
  appdb = host=db1.internal ...  ->  [primary] host = db1.internal

Unsupported (manual decision required):
  so_reuseport = 1         ->  no pgagroal equivalent;
                               decide whether you still need it
default_pool_size and min_pool_size are translated as-is (same key name, value copied unchanged), and auth_file becomes users_file. auth_type, auth_query, and auth_user have no pgagroal equivalent: they are listed under Unsupported, and the report adds a warning that tells you to set the authentication method in pgagroal_hba.conf (plus a users file for non-trust auth, or allow_unknown_users for transparent passthrough).

Setting mapping

How the settings a typical pgbouncer.ini contains line up with pgagroal. Anything without a clean equivalent is listed in the report for you to decide.

pgbouncer.inipgagroal equivalentNotes
listen_portport (in [pgagroal])Port the pooler accepts client connections on.
max_client_connmax_connectionsCap on total client connections to the pooler.
pool_modepipelinetransaction and session map across by name; how aggressively connections are reused.
[databases] entryDerived [primary] backendThe host= of the entry becomes the backend the pooler connects to.
default_pool_size / min_pool_sizedefault_pool_size / min_pool_sizeTranslated as-is — same key name, value copied unchanged.
auth_fileusers_filePath to the credentials file is translated.
auth_type / auth_query / auth_userNoneNo equivalent; reported as Unsupported with a warning to configure pgagroal_hba.conf (and a users file, or allow_unknown_users for passthrough).
Unknown keys (e.g. so_reuseport)NoneNot translated; listed in the report as a manual decision.

Cut over safely

The generated config is a reviewed starting point, not a guaranteed drop-in. Move in steps so you can fall back at any point.

  • Run in parallel. Deploy pgagroal alongside your existing PgBouncer rather than replacing it. Both poolers can front the same database while you validate.
  • Switch the connection string.Point your application’s connection string from the PgBouncer endpoint to the pgagroal pooler Service. Change one consumer first, not all of them at once.
  • Keep a rollback ready. To roll back, point the connection string back at PgBouncer. Because both run in parallel, rollback is a config change with no redeploy of the database.
This is not always a drop-in. Transaction pooling reuses a backend connection between transactions, so anything that relies on session state held across transactions — temporary tables, session-level SET, prepared statements, advisory locks — can behave differently after the switch. Test under realistic load before cutting over, and see Connection pooling for the pooling-mode trade-offs.

Next steps