Skip to content

Client drivers compatibility

PgDog is generally compatible with all PostgreSQL client drivers. Some of them are used heavily in production by our customers and users, and we know them to work well. Others, less so, but they are generally expected to be compatible. A lot of them are tested in our CI.

Some drivers have known compatibility or performance issues, documented below.

Client drivers

Driver Status Limitations
psycopg (Python) None.
psycopg2 (Python) Fully compatible but has some performance constraints.
asyncpg (Python) None.
ruby-pg (Ruby) None.
node-postgres (Node) None.
Postgres.js (Node) Needs additional configuration for prepared statements to work correctly.
Prisma (Node) Generates a lot of unique prepared statements, consider limiting the prepared statements cache.
Sequelize (Node) Uses node-postgres under the hood, no limitations.
PDO (PHP) None.
SQLx (Rust) None.
tokio_postgres (Rust) None.
pgx (Go) None.
lib/pq (Go) Needs additional configuration for prepared statements to work correctly.
sqlx (Go) Uses pgx under the hood, no limitations.
libpq (C/C++) None.
JDBC (Java) Manual routing requires a bit of tweaking.

Known issues

Some PostgreSQL client drivers have some performance or compatibility issues with PgDog. Most of them are only relevant if you're using load balancing or sharding.

JDBC

The Java PostgreSQL driver (JDBC) is using prepared statements to execute all commands, including BEGIN, SET, and simple queries that don't include parameters (e.g., $1, $2, etc.)

This is usually fine; however, if you're using manual routing, the comment can be cached client-side and cause incorrect query routing. To avoid this, enable the extendedForPrepared setting:

String url = "jdbc:postgresql://localhost:6432/pgdog?preferQueryMode=extendedForPrepared";
Connection conn = DriverManager.getConnection(url, "user", "password");

psycopg2

psycopg2 doesn't support prepared statements. It will use the simple protocol and inject parameters directly into the query string client-side.

This doesn't cause any query routing issues; however, PgDog can't effectively cache the query syntax tree and has to parse queries every time they are executed. This is computationally expensive. Consider switching to psycopg (version 3) or enabling our Rust-native query parser:

[general]
query_parser_engine = "pg_query_raw"

We benchmarked this to be 5 times faster than normal pg_query parsing, which should help.

Postgres.js

postgres Node driver uses a combination of named and unnamed prepared statements. For load balancing or sharding to work correctly, PgDog needs to cache all prepared statements, including unnamed ones (we call them "anonymous"). This is not the default behavior and requires the following setting:

[general]
prepared_statements = "extended_anonymous"

Prisma

Prisma doesn't correctly use the IN clause with arrays, causing it to generate a very large number of unique prepared statements. This is not a big problem, but if left unchecked, can cause heavy memory usage in PgDog. Consider setting a lower prepared statements cache limit:

[general]
prepared_statements_limit = 1_000

lib/pq

lib/pq (Go) uses unnamed prepared statements which PgDog has to cache for load balancing or sharding to work correctly. This is not the default behavior and requires the following setting:

[general]
prepared_statements = "extended_anonymous"