Settings
Configuration File Format
pg_doorman supports two configuration file formats:
- YAML (
.yaml,.yml) - The primary and recommended format for new configurations. - TOML (
.toml) - Supported for backward compatibility with existing configurations.
The format is automatically detected based on the file extension. Both formats support the same configuration options and can be used interchangeably.
Example YAML Configuration (Recommended)
general:
host: "0.0.0.0"
port: 6432
admin_username: "admin"
admin_password: "change_me_to_a_long_random_secret"
pools:
mydb:
server_host: "localhost"
server_port: 5432
pool_mode: "transaction"
users:
- username: "myuser"
password: "md5..." # hash from pg_shadow / pg_authid
pool_size: 40
Example TOML Configuration (Legacy)
[general]
host = "0.0.0.0"
port = 6432
admin_username = "admin"
admin_password = "change_me_to_a_long_random_secret"
[pools.mydb]
server_host = "localhost"
server_port = 5432
pool_mode = "transaction"
[[pools.mydb.users]]
username = "myuser"
password = "md5..." # hash from pg_shadow / pg_authid
pool_size = 40
Generate Command
The generate command can output configuration in either format. The format is determined by the output file extension. By default, the generated config includes detailed inline comments explaining every parameter.
# Generate YAML configuration (recommended)
pg_doorman generate --output config.yaml
# Generate TOML configuration (for backward compatibility)
pg_doorman generate --output config.toml
# Generate a complete reference config without PG connection
pg_doorman generate --reference --output config.yaml
# Generate reference config with Russian comments
pg_doorman generate --reference --ru --output config.yaml
# Generate config without comments (plain serialization)
pg_doorman generate --no-comments --output config.yaml
| Flag | Description |
|---|---|
--no-comments | Disable inline comments in generated config (by default, comments are included) |
--reference | Generate a complete reference config with example values, no PostgreSQL connection needed |
--russian-comments, --ru | Generate comments in Russian for quick start guide |
--format, -f | Output format: yaml (default) or toml. If --output is specified, format is auto-detected from file extension. This flag overrides auto-detection |
Include Files
Include files can be in either format, and you can mix formats. For example, a YAML main config can include TOML files and vice versa:
include:
files:
- "pools.yaml"
- "users.toml"
Human-Readable Values
pg_doorman supports human-readable formats for duration and byte size values, while maintaining backward compatibility with numeric values.
Duration Format
Duration values can be specified as:
- Plain numbers: interpreted as milliseconds (e.g.,
5000= 5 seconds) - String with suffix:
ms- milliseconds (e.g.,"100ms")s- seconds (e.g.,"5s"= 5000 milliseconds)m- minutes (e.g.,"5m"= 300000 milliseconds)h- hours (e.g.,"1h"= 3600000 milliseconds)d- days (e.g.,"1d"= 86400000 milliseconds)
Examples:
general:
# All these are equivalent (3 seconds):
# connect_timeout: 3000 # backward compatible (milliseconds)
# connect_timeout: "3s" # human-readable
# connect_timeout: "3000ms" # explicit milliseconds
connect_timeout: "3s"
idle_timeout: "10m" # 10 minutes
server_lifetime: "1h" # 1 hour
Byte Size Format
Byte size values can be specified as:
- Plain numbers: interpreted as bytes (e.g.,
1048576= 1 MB) - String with suffix (case-insensitive):
B- bytes (e.g.,"1024B")KorKB- kilobytes (e.g.,"1K"or"1KB"= 1024 bytes)MorMB- megabytes (e.g.,"1M"or"1MB"= 1048576 bytes)GorGB- gigabytes (e.g.,"1G"or"1GB"= 1073741824 bytes)
Note: Uses binary prefixes (1 KB = 1024 bytes, not 1000 bytes).
Examples:
general:
# All these are equivalent (256 MB):
# max_memory_usage: 268435456 # backward compatible (bytes)
# max_memory_usage: "256MB" # human-readable
# max_memory_usage: "256M" # short form
max_memory_usage: "256MB"
unix_socket_buffer_size: "1MB" # 1 MB
worker_stack_size: "8MB" # 8 MB
General Settings
host
Listen host (TCP v4 only).
Default: "0.0.0.0".
port
Listen port for incoming connections.
Default: 5432.
backlog
TCP backlog for incoming connections. A value of zero sets the max_connections as value for the TCP backlog.
Default: 0.
max_connections
The maximum number of clients that can connect to the pooler simultaneously. When this limit is reached:
- A client connecting without SSL will receive the expected error (code:
53300, message:sorry, too many clients already). - A client connecting via SSL will see a message indicating that the server does not support the SSL protocol.
Default: 8192.
max_concurrent_creates
Maximum number of server connections that can be created concurrently per pool. This setting uses a semaphore to limit parallel connection creation, which significantly improves performance during cold start and burst scenarios.
Higher values allow faster pool warm-up but may increase load on the PostgreSQL server during connection storms. Lower values provide more gradual connection creation.
Default: 4.
tls_mode
The TLS mode for incoming connections. It can be one of the following:
allow- TLS connections are allowed but not required. The pg_doorman will attempt to establish a TLS connection if the client requests it.disable- TLS connections are not allowed. All connections will be established without TLS encryption.require- TLS connections are required. The pg_doorman will only accept connections that use TLS encryption.verify-full- TLS connections are required and the pg_doorman will verify the client certificate. This mode provides the highest level of security.
Default: "allow".
tls_ca_cert
CA certificate file used to verify client certificates. Required when tls_mode is set to verify-full.
Default: None.
tls_private_key
Path to the private key file for TLS connections. Required to enable TLS for incoming client connections. Must be used together with tls_certificate.
Default: None.
tls_certificate
Path to the certificate file for TLS connections. Required to enable TLS for incoming client connections. Must be used together with tls_private_key.
Default: None.
tls_rate_limit_per_second
Limit the number of simultaneous attempts to create a TLS session. Any value other than zero implies that there is a queue through which clients must pass in order to establish a TLS connection. In some cases, this is necessary in order to launch an application that opens many connections at startup (the so-called "hot start").
Default: 0.
daemon_pid_file
Enabling this setting enables daemon mode. Comment this out if you want to run pg_doorman in the foreground with -d.
Default: "/tmp/pg_doorman.pid".
syslog_prog_name
When specified, pg_doorman starts sending messages to syslog (using /dev/log or /var/run/syslog). Comment this out if you want to log to stdout.
Default: None.
log_client_connections
Log client connections for monitoring.
Default: true.
log_client_disconnections
Log client disconnections for monitoring.
Default: true.
worker_threads
Number of Tokio runtime worker threads (OS threads) for serving client connections.
Performance scales linearly up to the number of CPU cores.
Also determines the shard count for internal concurrent hash maps (worker_threads * 4, rounded to nearest power of 2, minimum 4).
In Kubernetes, set this explicitly — automatic CPU detection may report the host's cores instead of the container's limit.
Default: 4.
worker_cpu_affinity_pinning
Bind each worker thread to a separate CPU core (sched_setaffinity). Disabled when fewer than 3 cores are available.
Default: false.
tokio_global_queue_interval
Tokio runtime settings. Controls how often the scheduler checks the global task queue. Modern tokio versions handle this well by default, so this parameter is optional.
Default: not set (uses tokio's default).
tokio_event_interval
Tokio runtime settings. Controls how often the scheduler checks for external events (I/O, timers). Modern tokio versions handle this well by default, so this parameter is optional.
Default: not set (uses tokio's default).
worker_stack_size
Tokio runtime settings. Sets the stack size for worker threads. Modern tokio versions handle this well by default, so this parameter is optional.
Default: not set (uses tokio's default).
max_blocking_threads
Tokio runtime settings. Sets the maximum number of threads for blocking operations. Modern tokio versions handle this well by default, so this parameter is optional.
Default: not set (uses tokio's default).
connect_timeout
Maximum time to wait when establishing a new connection to a PostgreSQL server. If the connection cannot be established within this period, the attempt is aborted. Similar to PgBouncer's server_connect_timeout.
Default: 3000 (3 sec).
query_wait_timeout
Maximum time a client query can wait for a server connection when the pool is fully utilized. If no server connection becomes available within this period, the client receives an error. Similar to PgBouncer's query_wait_timeout.
Default: 5000 (5 sec).
idle_timeout
Close a server connection that has been idle (not checked out by any client) longer than this value.
Only applies to connections that have served at least one client request. Prewarmed or replenished
connections that were never checked out are not subject to idle_timeout — they are only closed
when server_lifetime expires. Each connection gets ±20% jitter to prevent synchronized mass closures.
Set to 0 to disable. Similar to PgBouncer's server_idle_timeout.
Default: 600000 (10 min).
server_lifetime
Maximum age of a server connection. When a connection exceeds this age and becomes idle,
it is closed during the next retain cycle. Active transactions are not interrupted.
Applies to all connections, including prewarmed ones that were never checked out by a client.
Each connection gets ±20% jitter to prevent thundering herd. Set to 0 to disable.
Similar to PgBouncer's server_lifetime.
Default: 1200000 (20 min).
retain_connections_time
Interval for checking and closing idle connections that exceed idle_timeout or server_lifetime.
The retain task runs periodically at this interval to clean up expired connections.
Default: 30000 (30 sec).
retain_connections_max
Maximum number of idle connections to close per retain cycle.
When set to 0, all idle connections that exceed idle_timeout or server_lifetime will be closed immediately.
When set to a positive value, at most that many connections will be closed per cycle across all pools.
This parameter controls how aggressively pg_doorman closes idle connections. With the default value of 3,
up to 3 connections are closed per retain cycle, providing controlled cleanup. If you need faster cleanup of
expired connections, set to 0 (unlimited) to close all expired connections in each retain cycle.
Default: 3.
server_idle_check_timeout
Time after which an idle server connection should be checked before being given to a client. This helps detect dead connections caused by PostgreSQL restart, network issues, or server-side idle timeouts.
When a connection has been idle in the pool longer than this timeout, pg_doorman will send a minimal query (;)
to verify the connection is still alive before returning it to the client. If the check fails, the connection
is discarded and a new one is obtained.
Set to 0 to disable the check (not recommended for production environments with potential network instability
or PostgreSQL restarts).
Default: 60s (60 seconds).
server_round_robin
Controls which idle server connection is picked for the next transaction.
false (LRU): reuses the most recently returned connection. Keeps fewer connections hot, better for PostgreSQL shared buffer locality.
true (Round Robin): rotates across all idle connections evenly.
Similar to PgBouncer's server_round_robin.
Default: false.
sync_server_parameters
In transaction mode, different transactions from the same client may run on different backend
connections. With sync_server_parameters = true, pg_doorman applies the client's session
parameters to the selected backend before the transaction starts.
Values come from two places:
-
PostgreSQL
ParameterStatusmessages:client_encoding,DateStyle,IntervalStyle,TimeZone,standard_conforming_strings,application_name. PostgreSQL reports changes to these parameters over the protocol. -
Safe client
StartupMessageparameters (new in pg_doorman 3.10): any parameter sent by the client during connection startup, except server-managed or read-only names (is_superuser,server_version,lc_collate,transaction_isolation, ...) and the protocol-reserved_pq_.prefix. This lets clients setsearch_path,default_transaction_isolation,role, and similar planner inputs once at connection time. Configuredstartup_parametersalways override the client packet.
Important limits:
-
pg_doorman tracks startup parameters and PostgreSQL-reported parameters only. If a client runs
SET search_path = ...or changes another unreported planner GUC after connection startup, pg_doorman does not see that change. Later prepared-statement reuse can then use a plan built under older planner state. Clients that need runtime planner-GUC changes should set those values inStartupMessage, runDISCARD ALLor reconnect after changing them, or disableprepared_statementsfor the pool. -
The prepared-statement cache key includes the query text, parameter OIDs, and a digest of these startup-time planner GUCs:
search_path,default_transaction_isolation,default_transaction_read_only,default_text_search_config,role. Other planner inputs (TimeZone,DateStyle,plan_cache_mode,enable_*, JIT cost knobs, extension GUCs) are not part of the key. If the same prepared query runs under different values of those parameters, disableprepared_statementsfor the pool or pin the parameters at the role/database level.
Adds one extra SET/RESET round trip only when the backend state differs from the client state. If
you only need application_name visibility in pg_stat_activity, use the pool-level
application_name setting instead.
Default: false.
tcp_so_linger
By default, pg_doorman send RST instead of keeping the connection open for a long time.
Default: 0.
tcp_no_delay
TCP_NODELAY to disable Nagle's algorithm for lower latency.
Default: true.
tcp_keepalives_count
Number of unacknowledged TCP keepalive probes before the connection is considered dead and closed.
Default: 5.
tcp_keepalives_idle
Keepalive enabled by default and overwrite OS defaults.
Default: 5.
tcp_keepalives_interval
Interval in seconds between individual TCP keepalive probes after the initial idle period (tcp_keepalives_idle) has passed.
Default: 5.
tcp_user_timeout
Sets the TCP_USER_TIMEOUT socket option for client connections (in seconds). This option specifies
the maximum time that transmitted data may remain unacknowledged before TCP will forcibly close the
connection. This helps detect dead client connections faster than keepalive probes when the connection
is actively sending data but the remote end has become unreachable (e.g., network failure, client crash).
When set to a non-zero value, if data remains unacknowledged for this duration, the connection will be terminated. Use it to avoid 15-16 minute delays caused by TCP retransmission timeout when keepalive cannot help (e.g., during active data transmission).
Note: This option is only supported on Linux. On other operating systems, this setting is ignored.
Set to 0 to disable (use OS default).
Default: 60.
tcp_socket_buffer_size
Kernel SO_RCVBUF/SO_SNDBUF limits for accepted client TCP sockets, accepted web TCP sockets, and outbound backend TCP sockets.
With the default 0, pg_doorman does not call setsockopt(SO_RCVBUF/SO_SNDBUF) and Linux TCP autotuning stays in charge. Per-connection receive buffers can grow on demand up to net.ipv4.tcp_rmem[2] (commonly 6 MiB on Ubuntu/RHEL). That memory is not process RSS; depending on kernel and cgroup mode it may appear separately as socket memory, for example as sock in cgroup v2 memory.stat, or mostly as host-level kernel memory. If MemFree jumps after a pg_doorman restart, confirm the source with ss -m, /proc/net/sockstat, cgroup v2 memory.current, and memory.stat key sock.
Setting a non-zero value calls setsockopt(SO_RCVBUF/SO_SNDBUF) once per configured TCP socket. This disables autotuning for that socket and sets fixed send/receive buffer limits. Linux internally doubles the requested values — see man 7 socket — and may clamp them by net.core.rmem_max / net.core.wmem_max. Check /proc/sys/net/core/rmem_max and /proc/sys/net/core/wmem_max before choosing values above the OS default. getsockopt, ss -m, and pg_doorman DEBUG logs show the kernel-applied values.
The rough Linux limit is 4 * tcp_socket_buffer_size * tcp_socket_count: send and receive buffers are both configured, and Linux doubles each requested value internally. For example, tcp_socket_buffer_size = 65536 sets about 256 KiB of send+receive limits per TCP socket, so 60 TCP sockets have about 15 MiB of configured kernel buffer limits before sk_buff overhead. Count client TCP sockets, web TCP sockets, and backend TCP sockets. Actual resident memory still depends on queued data.
This setting is primarily a memory cap. Suggested starting range for OLTP traffic inside one datacenter: 64 KiB – 256 KiB. Do not set less than 64 KiB unless measurements show it is safe. WAN links, cross-zone traffic, large result sets, and bulk transfers may need a larger value or the default autotuning behaviour.
The value is applied when pg_doorman configures a TCP socket: on accepted client sockets, accepted web sockets, outbound backend sockets, and migrated client sockets reconstructed during binary upgrade. SIGHUP reload does not revisit already-open sockets. To apply a new value to existing sessions, use binary upgrade for migrated clients, reconnect/drain pools for backend sockets, or restart when reconnects are acceptable.
Equivalent of PgBouncer's tcp_socket_buffer parameter. Odyssey and PgCat have no analogue and inherit the kernel autotuner's behaviour.
Default: 0.
unix_socket_buffer_size
Buffer size for read and write operations when connecting to PostgreSQL via a unix socket.
Default: 1048576.
unix_socket_dir
Directory for Unix domain socket listener. Creates .s.PGSQL.
Default: null.
unix_socket_mode
Permission mode applied to the Unix domain socket file .s.PGSQL.<port> immediately after bind(). Specified as an octal string (e.g. "0600", "0660", "0666"). Only the lowest 9 bits are honored — setuid/setgid/sticky bits are rejected.
The default "0600" restricts socket access to the user running pg_doorman. To let other local users connect, set a more permissive mode such as "0660" (group access) or "0666" (any local user). When loosening the mode, ensure the parent directory permissions allow traversal by the intended group.
Default: "0600".
admin_username
Access to the virtual admin database is carried out through the administrator's username and password.
Default: "admin".
admin_password
Access to the virtual admin database is carried out through the administrator's username and password. It should be replaced with your secret.
Default: "admin".
prepared_statements
Enables prepared-statement remapping and caching. When disabled, pg_doorman forwards
Parse and Bind without rewriting them through the pool-level prepared-statement cache.
If this is true, prepared_statements_cache_size must be greater than 0.
Default: true.
prepared_statements_cache_size
Cache size of prepared statements at the pool level (shared across all clients connecting to the same pool). This cache stores the mapping from query hash to rewritten prepared statement name.
This is not the disable switch. To disable prepared-statement remapping, set
prepared_statements: false; pg_doorman rejects a general prepared_statements_cache_size
of 0 while prepared_statements is enabled.
For an end-to-end picture of how this knob interacts with server_prepared_statements_cache_size,
client_anonymous_prepared_cache_size, and the query interner, see the
Anonymous Parse caching tutorial.
Default: 8192.
server_prepared_statements_cache_size
Sizes the per-backend LruCache<String, ()> of DOORMAN_<N> names independently of the pool-level cache.
When unset (default), inherits the resolved prepared_statements_cache_size for that pool. A per-pool
override on this field takes precedence over this general value.
Lower this knob below the pool size when backends carry too many DOORMAN_<N> rows
(pg_prepared_statements near the cap, plan memory ballooning) or when faster Close recycling is desired
without shrinking pool-level hit rate. Forced to 0 when prepared_statements: false.
Default: not set (inherits prepared_statements_cache_size).
client_anonymous_prepared_cache_size
Bounds the Anonymous part of the per-client prepared-statement cache. Anonymous statements are issued without an explicit name and are typically short-lived; the LRU caps how many of them a single client can accumulate before the oldest one is evicted.
When unset (default), inherits the resolved prepared_statements_cache_size for the pool. Set to 0 to
disable the LRU and fall back to an unlimited map for Anonymous entries; set to a number to bound the
per-client cache independently of the pool size.
The Named part of the per-client cache (statements created with an explicit name via PREPARE or the
extended-query Parse) is always unbounded — this knob does not affect it. Named statements stay
cached for the lifetime of the client connection.
Default: not set (inherits prepared_statements_cache_size).
query_interner_gc_interval_seconds
The query interner runs a two-cycle mark-and-sweep collector. Named entries
are evicted when nothing outside the interner holds the Arc<str>; anonymous
entries are evicted when idle longer than query_interner_anon_idle_ttl_seconds.
This knob controls how often the collector wakes up. The actual sweep tick
is gc_interval / 4, so an entry marked on cycle N has roughly a
quarter-interval before cycle N+1 evicts it; any access during that window
clears the mark.
Lower values shrink the interner faster after disconnect waves at the cost
of more CPU. Setting this to 0 is rejected at startup.
Restart-only: changes to this knob take effect only after a restart; a config reload won't change the running sweep cadence.
Default: 60.
query_interner_anon_idle_ttl_seconds
Bounds the upper memory cost of pg_doorman remembering the SQL text of an anonymous prepared statement after the last Bind or Parse referencing the same hash. Once an anonymous entry has been idle longer than this many seconds it is marked, then evicted on the next sweep that still sees it as idle.
Setting this to 0 disables TTL eviction entirely. Anonymous entries
live until the process restarts. This matches the pre-3.7 behaviour and
is the right choice for legacy deployments that rely on cross-batch
unnamed prepared statements; everywhere else, leave the default.
Live-reloadable: re-read on every sweep, so a config reload changes the effective TTL without a restart.
Default: 60.
message_size_to_be_stream
When a PostgreSQL DataRow message exceeds this threshold, pg_doorman switches to streaming mode:
data is forwarded to the client in 4 KB chunks instead of buffering the entire message.
This prevents OOM on queries that return very large rows (e.g., tables with big bytea/text columns).
The threshold itself defaults to 1 MB.
Default: 1048576 (1 MB).
scaling_warm_pool_ratio
Warm pool ratio as a percentage (0-100). When the pool size is below this threshold
of max_size, new connections are created immediately. Above this threshold, the
pool first spins via fast retries, then enters an event-driven anticipation loop
that waits for a returned idle connection. The loop is bounded by the client's
remaining query_wait_timeout minus a 500 ms reserve for the create path, so it
cannot push the caller past its own wait deadline.
Default: 20.
scaling_fast_retries
Number of fast retries using yield_now() for low-latency waiting when checking out
connections above the warm pool threshold. Each retry takes approximately 1-5μs.
After exhausting fast retries, the pool enters an event-driven anticipation loop
bounded by the client's remaining query_wait_timeout.
Default: 10.
scaling_max_parallel_creates
Bounded burst limiter for connection creation. Without this cap, N parallel
timeout_get callers that miss the idle pool each independently issue a backend
connect, producing thundering-herd bursts under load. With the cap, only this
many creates run concurrently per pool; the rest wait briefly on a Notify and
then either pick up a freshly returned idle connection or take the next create
slot. Default 2 is a compromise between throughput and burst smoothing.
Default: 2.
max_memory_usage
Total memory budget for internal buffers holding in-flight query data across all client connections. When this limit is reached, pg_doorman rejects new queries with an error until existing queries complete and free their buffers. Protects the pooler process from OOM under heavy load or large result sets.
Default: 268435456 (256 MB).
shutdown_timeout
During graceful shutdown (SIGTERM), pg_doorman waits up to this long for in-flight transactions to complete before forcibly closing connections.
Default: 10000 (10 sec).
proxy_copy_data_timeout
Maximum time to wait for data copy operations during proxying, in milliseconds.
Default: 15000 (15 sec).
server_tls_mode
TLS mode for outgoing connections to PostgreSQL servers.
allow— Try plain first; if server rejects, retry with TLS. Matches libpq sslmode=allow (default).disable— TLS is not used.prefer— TLS is used if the server supports it; plain connection otherwise.require— TLS is required, but the server certificate is not verified.verify-ca— TLS is required and the server certificate is verified againstserver_tls_ca_cert.verify-full— TLS is required, the certificate is verified, and the server hostname must match the certificate.
Default: "allow".
server_tls_ca_cert
CA certificate for verifying PostgreSQL server certificates. Required when server_tls_mode is verify-ca or verify-full.
Default: None.
server_tls_certificate
Client certificate for mTLS with PostgreSQL servers. Pair with server_tls_private_key.
Default: None.
server_tls_private_key
Private key for the mTLS client certificate. Pair with server_tls_certificate.
Default: None.
hba
The list of IP addresses from which it is permitted to connect to the pg-doorman.
Default: [].
pg_hba
New-style client access control in native PostgreSQL pg_hba.conf format. This allows you to define fine-grained access rules similar to PostgreSQL, including per-database, per-user, address ranges, and TLS requirements.
You can specify general.pg_hba in three ways:
- As a multi-line string with the contents of a
pg_hba.conffile - As an object with
paththat points to a file on disk - As an object with
contentcontaining the rules as a string
Examples:
[general]
# Inline content (triple-quoted TOML string)
pg_hba = """
# type database user address method
host all all 10.0.0.0/8 md5
hostssl all all 0.0.0.0/0 scram-sha-256
hostnossl all all 192.168.1.0/24 trust
"""
# Or load from file
# pg_hba = { path = "./pg_hba.conf" }
# Or embed as a single-line string
# pg_hba = { content = "host all all 127.0.0.1/32 trust" }
Supported fields and methods:
- Connection types:
local,host,hostssl,hostnossl(TLS-aware matching is honored) - Database matcher: a name or
all - User matcher: a name or
all - Address: CIDR form like
1.2.3.4/32or::1/128(required for non-localrules) - Methods:
trust,md5,scram-sha-256(unknown methods are parsed but treated as not-allowed by the checker)
Precedence and compatibility:
general.pg_hbasupersedes the legacygeneral.hbalist. You cannot set both at the same time; configuration validation will reject this combination.- Rules are evaluated in order; the first matching rule decides the outcome.
Behavior of method = trust:
- When a matching rule has
trust, PgDoorman will accept the connection without requesting a password. This mirrors PostgreSQL behavior. - Specifically, if
trustmatches, PgDoorman will skip password verification even if the user has anmd5orscram-sha-256password stored. This affects both MD5 and SCRAM flows. - TLS constraints from the rule are respected:
hostsslrequires TLS,hostnosslforbids TLS.
Admin console access:
general.pg_hbarules apply to the special admin databasepgdoormanas well.- This means you can allow admin access with the
trustmethod when a matching rule is present, for example:host pgdoorman admin 127.0.0.1/32 trust
Notes and limitations:
- Only a minimal subset of
pg_hba.confis supported that is sufficient for most proxy use-cases (type, database, user, address, method). Additional options (likeclientcert) are currently ignored. - For authentication methods other than
trust, PgDoorman performs the corresponding challenge/response with the client. - For Talos/JWT/PAM flows configured at the pool/user level,
truststill bypasses the client password prompt; however, those modes may be used whentrustdoes not match.
pooler_check_query
When a client sends this exact query as a SimpleQuery, pg_doorman serves it through a per-pool response cache. The first matching probe in each pool's lifetime is forwarded to PostgreSQL and the full response is captured. Subsequent matching probes are answered from the cache without touching the backend.
The cache is keyed by the query string. A RELOAD that changes pooler_check_query invalidates
the cache on the next ping; the new value triggers one fresh backend probe and is then served
from cache until the value changes again. A reload that keeps the same value keeps the cached
response. ErrorResponse from the backend is forwarded to the client unchanged and is never
cached, so the next probe retries against PostgreSQL.
Cold-pool behavior changed: the first probe per pool now does one PostgreSQL round-trip even
for the default ;. If PostgreSQL is unreachable at that moment, the probing client sees a
probe failure instead of an unconditional OK. The earlier hardcoded local answer reported the
pooler as healthy even when PostgreSQL was down, and made non-empty values such as select 1
return an empty response.
Operator contract. The query must be stable: the same input must always produce the same
bytes, with no side effects. Safe values: ;, select 1, select 'pg_doorman', select version().
Unsafe values that the cache will silently freeze:
select now(),select clock_timestamp()— the cached timestamp never advances.select pg_is_in_recovery()— a failover flips the role on PostgreSQL but the cached response still reports the old role.select count(*) from <table>— the cached count is whatever the first probe observed.UPDATE,INSERT,DELETE,CALL,DO— the side effect runs once and the success response is cached forever.
Cache hit rate is exported as two counters without labels:
pg_doorman_pooler_check_query_backend_total (probes forwarded to PostgreSQL) and
pg_doorman_pooler_check_query_cache_total (probes served from cache). The ratio
cache_total / (cache_total + backend_total) is the hit rate.
Default: ";".
startup_parameters
Map of PostgreSQL configuration parameter names to string values. pg_doorman writes them into each new backend StartupMessage; PostgreSQL stores them as the session reset defaults, so client RESET ALL / DISCARD ALL returns to these values.
Cascade order: general.startup_parameters, then pools.<name>.startup_parameters, then the optional startup_parameters JSON column returned by passthrough auth_query. Later layers win per key. Dedicated-mode auth_query pools ignore the per-user column because one shared backend serves multiple roles.
Validation at config load rejects reserved protocol keys (user, database, replication, options, anything starting with _pq_.), invalid GUC names, null bytes, and per-level maps that exceed the startup-parameter budget. Before each backend startup, pg_doorman checks the resolved parameter set against PG's MAX_STARTUP_PACKET_LENGTH (10 000 bytes). Any overflow rejects backend startup with SQLSTATE 53400 (configuration_limit_exceeded) instead of sending a partial or empty StartupMessage.
If PostgreSQL rejects a parameter at backend startup, pg_doorman returns PostgreSQL's ErrorResponse to the client unchanged. There is no retry with the key removed, and pg_doorman does not automatically disable that key for the pool. The cumulative count is exported as pg_doorman_backend_startup_parameter_errors_total{pool, sqlstate}; the parameter name and username are written to the corresponding warning log line.
Inspect the resolved per-pool values with SHOW STARTUP_PARAMETERS or the /api/pools REST endpoint.
Default: {} (empty).