Configuration

PgCache supports three configuration methods: a TOML config file, CLI arguments, and Docker environment variables. These can be combined — CLI arguments override TOML file values, and Docker environment variables are mapped to CLI arguments by the container entrypoint.

Configuration Methods

MethodUsageBest For
Environment variablesUPSTREAM_URL=postgres://...Docker deployments (recommended)
CLI argumentsPassed via Docker commandOverriding specific values
TOML fileMounted into containerVersion-controlled config

TOML Configuration Reference

[origin] — Origin Database Connection

The PostgreSQL database that PgCache caches queries for.

FieldTypeRequiredDefaultDescription
hoststringyes—Origin database hostname
portintegeryes—Origin database port
userstringyes—Database user
passwordstringno—Database password
databasestringyes—Database name
ssl_modestringnodisableTLS mode: disable, require, or verify-full

[replication] — Replication Connection (Optional)

Override connection settings for CDC logical replication. Every field is optional and cascades from [origin] when not specified. This is useful when your application connects through a connection pooler like PgBouncer, but CDC replication needs a direct connection to PostgreSQL.

FieldTypeDefaultDescription
hoststringorigin hostReplication host
portintegerorigin portReplication port
userstringorigin userReplication user
passwordstringorigin passwordReplication password
databasestringorigin databaseReplication database
ssl_modestringorigin ssl_modeTLS mode: disable, require, or verify-full

[cdc] — Change Data Capture

Settings for PostgreSQL logical replication. PgCache creates and manages the publication and replication slot automatically on the origin database using these names.

FieldTypeRequiredDefaultDescription
publication_namestringyes—Name of the publication PgCache creates on the origin
slot_namestringyes—Name of the logical replication slot PgCache creates on the origin

[listen] — Proxy Listener

FieldTypeRequiredDefaultDescription
socketstringyes—Address and port to listen on (e.g., 0.0.0.0:5432)

[metrics] — Prometheus Metrics (Optional)

FieldTypeRequiredDefaultDescription
socketstringyes—Address and port for the metrics HTTP endpoint. A wildcard address (0.0.0.0 or [::]) binds dual-stack where the host supports it, so localhost resolves over IPv4 or IPv6; the proxy listener binds its address as given

Top-Level Settings

General

FieldTypeRequiredDefaultDescription
num_workersintegeryes—Number of worker threads for handling connections. Also sets the bounds of the cache serve pool, which sizes itself between num_workers × 2 and num_workers × 8 connections
population_workers_minintegernomax(num_workers, 2)Floor and starting size of the population worker pool. Each worker holds one origin and one cache connection
population_workers_maxintegernonum_workers × 8Ceiling on the population worker pool — the maximum number of concurrent population queries against the origin. The pool grows toward it only while population queue wait is high and added workers raise throughput. A value below the default floor also lowers the floor
log_levelstringno—Log level filter. Supports simple levels ("info", "debug") and module-specific filters ("pgcache_lib::cache=debug,info")
telemetrybooleannotrueAnonymous telemetry reporting. Set to false to disable. See Telemetry for details on what is collected

Cache Behavior

The fields in this section plus log_level can be changed at runtime via the HTTP admin API (PUT /config) without restarting. See Monitoring for the admin endpoints.

FieldTypeRequiredDefaultDescription
cache_sizeintegerno—Deprecated and ignored. Superseded by disk_limit; setting it logs a deprecation warning and has no effect
cache_policystringnoclockEviction policy: clock (second-chance) or fifo (oldest first)
admission_thresholdintegerno1Number of times a query must be seen before cache admission (clock policy only; 1 admits on first occurrence)
mv_size_ratiointegerno10Materialized result size gate (row-reduction test). A shape-eligible query (aggregate, GROUP BY, DISTINCT, etc.) passes this gate when result_rows × mv_size_ratio ≤ source_rows at first population — i.e. the result is at least this many times smaller than the input. A query is materialized if it passes either this gate or mv_compute_min_rows. Window functions materialize unconditionally
mv_compute_min_rowsintegerno1000Materialized-view compute-avoidance gate. A shape-eligible query passes this gate when its population source-row count is at least this value — so large inputs aren’t recomputed from source rows on every serve, regardless of how much the result reduces them. A query is materialized if it passes either this gate or mv_size_ratio
memo_cache_sizeintegerno67108864Total byte budget for the in-process result memo, an in-memory tier that serves the hottest queries inline without a cache-database round-trip. Default 64 MiB; 0 disables it
memory_limitintegerno—Absolute ceiling (bytes) on pgcache’s total memory footprint (the pgcache process plus the cache Postgres it manages). When unset, the ceiling is 80% of detected RAM (cgroup-aware in containers: the tightest limit on the cgroup ancestor chain applies, and usage is measured as the working set, excluding reclaimable page cache). As whole-system used memory approaches the ceiling, registration of new distinct queries is throttled — they are forwarded to origin instead of cached — bounding memory under high query cardinality. A configured value can only lower the effective ceiling, never raise it above 80% of RAM
disk_limitintegerno—Cap (bytes) on space used on the cache volume — the disk analogue of memory_limit. When the volume’s used space exceeds it, registration of new queries is throttled and cache tables are dropped to reclaim space. When unset, the limit auto-derives from the cache volume’s live free space, keeping a reserve free
allowed_tablesarrayno—Only cache queries referencing these tables. Supports unqualified ("orders") and schema-qualified ("audit.orders") names. If omitted, all tables are cacheable

Pinned Queries

FieldTypeRequiredDefaultDescription
pinned_queriesarrayno—SQL queries to pin in cache at startup. Pinned queries are pre-populated, protected from eviction, and auto-readmitted after CDC invalidation
pinned_tablesarrayno—Tables to pin in cache. Each table is expanded to SELECT * FROM {table} and merged with pinned_queries

TLS

FieldTypeRequiredDefaultDescription
tls_certstringno—Path to TLS certificate (PEM) for client connections
tls_keystringno—Path to TLS private key (PEM) for client connections

Full Example Configuration

num_workers = 4
# disk_limit = 10737418240     # max cache-volume bytes used; unset auto-derives from free space
# cache_policy = "clock"       # or "fifo"
# admission_threshold = 1      # clock policy only
log_level = "info"

# Optional: restrict caching to specific tables
# allowed_tables = ["users", "orders", "products"]

# Optional: pin queries in cache at startup
# pinned_queries = [
#     "SELECT * FROM settings",
#     "SELECT * FROM categories",
# ]

# Optional: pin entire tables (shorthand for pinned_queries)
# pinned_tables = ["settings", "categories"]

[origin]
host = "db.example.com"
port = 5432
user = "app_user"
password = "secret"
database = "myapp"
ssl_mode = "require"

# Optional: override replication connection
# Useful when origin is behind PgBouncer
[replication]
host = "db-direct.example.com"
port = 5432

[cdc]
publication_name = "pgcache_pub"
slot_name = "pgcache_slot"

[listen]
socket = "0.0.0.0:6432"

[metrics]
socket = "0.0.0.0:9090"

CLI Arguments Reference

All TOML fields can be set via command-line arguments. CLI values override TOML values.

FlagDescription
-c, --configPath to TOML configuration file
--config_createCreate the config file if missing and persist dynamic (PUT /config) changes to it; a missing file is not an error
--origin_hostOrigin database host
--origin_portOrigin database port
--origin_userOrigin database user
--origin_passwordOrigin database password
--origin_databaseOrigin database name
--origin_ssl_modeOrigin TLS mode (disable, require, or verify-full)
--replication_hostReplication host override
--replication_portReplication port override
--replication_userReplication user override
--replication_passwordReplication password override
--replication_databaseReplication database override
--replication_ssl_modeReplication TLS mode override
--cdc_publication_nameLogical replication publication name
--cdc_slot_nameLogical replication slot name
--listen_socketListen address and port
--num_workersNumber of worker threads
--population_workers_minPopulation worker pool floor (default max(num_workers, 2))
--population_workers_maxPopulation worker pool ceiling (default num_workers × 8)
--cache_sizeDeprecated and ignored; use --disk_limit
--cache_policyEviction policy (clock or fifo)
--admission_thresholdQuery admission threshold (clock policy only)
--mv_size_ratioMaterialized result size gate (default 10)
--mv_compute_min_rowsMaterialized-view compute-avoidance gate — also materializes any input of at least this many source rows (default 1000)
--memo_cache_sizeIn-process result memo byte budget (default 64 MiB; 0 disables)
--memory_limitAbsolute RSS ceiling in bytes for registration throttling (default: 80% of RAM; can only lower)
--disk_limitCap (bytes) on cache-volume space used before throttling + table drops (default: auto from free disk)
--tls_certTLS certificate file path
--tls_keyTLS private key file path
--metrics_socketPrometheus metrics listen address
--log_levelLog level filter
--allowed_tablesComma-separated list of tables to cache
--pinned_queriesSemicolon-separated queries to pin in cache
--pinned_tablesComma-separated tables to pin in cache
--telemetry_offDisable anonymous telemetry reporting
--checkCheck that the origin is ready for PgCache (connection, version, wal_level, slots, privileges, primary keys, views, RLS), print a report and exit. Exit status 1 when a check fails. Cache settings are not needed; the Docker image exposes this as pgcache check

Docker Environment Variables

When running the PgCache Docker image, these environment variables are available. They map to the entrypoint’s CLI options.

The origin database can be given either as a single UPSTREAM_URL or as individual ORIGIN_* fields; when both are set, the individual fields override the URL. The same applies to the replication connection (REPLICATION_URL vs the REPLICATION_* fields). Individual fields avoid URL-encoding credentials that contain special characters.

VariableDescriptionDefault
UPSTREAM_URLOrigin database URL (postgres://user:pass@host:port/db)— (required unless ORIGIN_HOST or CONFIG_FILE set)
ORIGIN_HOSTOrigin host (alternative to UPSTREAM_URL; overrides the URL)—
ORIGIN_PORTOrigin port5432
ORIGIN_USEROrigin userpostgres
ORIGIN_PASSWORDOrigin password—
ORIGIN_DATABASEOrigin database—
ORIGIN_SSL_MODEOrigin TLS mode (disable, require, verify-full)disable
CONFIG_FILEPath to TOML config file (mounted into container)—
CONFIG_CREATESet to 1/true to create CONFIG_FILE if missing and persist dynamic (PUT /config) changes across restarts—
REPLICATION_URLReplication connection URL (defaults to upstream)—
REPLICATION_HOSTOverride replication host—
REPLICATION_PORTOverride replication port—
REPLICATION_USEROverride replication user—
REPLICATION_DATABASEOverride replication database—
REPLICATION_PASSWORDOverride replication password—
REPLICATION_SSL_MODEOverride replication TLS mode—
LISTEN_PORTProxy listen port5432
METRICS_PORTPrometheus metrics port9090
NUM_WORKERSNumber of worker threadsauto (≈1 per allocated CPU, min 2)
PUBLICATIONPublication namepgcache_pub
SLOTReplication slot namepgcache_slot
CDC_SUFFIXSuffix appended to publication and slot names—
CACHE_SIZEDeprecated and ignored. Superseded by DISK_LIMIT—
DISK_LIMITCap (bytes) on cache-volume space used before disk-pressure reclaim engagesauto from free disk
CACHE_POLICYCache eviction policy: clock or fifoclock
ADMISSION_THRESHOLDNumber of times a query must be seen before caching1
MV_SIZE_RATIOMaterialized result size gate (row-reduction test): a shape-eligible query passes when result_rows × MV_SIZE_RATIO ≤ source_rows10
MV_COMPUTE_MIN_ROWSMaterialized-view compute-avoidance gate: a shape-eligible query is also materialized when its source-row count reaches this value1000
MEMO_CACHE_SIZEIn-process result memo byte budget (0 disables)67108864 (64 MiB)
MEMORY_LIMITAbsolute RSS ceiling in bytes for registration throttling (can only lower)80% of RAM
ALLOWED_TABLESComma-separated list of tables to cache (default: all)—
PINNED_QUERIESSemicolon-separated queries to pin in cache—
PINNED_TABLESComma-separated tables to pin in cache—
LOG_LEVELLog level filter (e.g., debug, info, pgcache_lib::cache=debug)—
PGCACHE_POPULATION_WORKERS_MINPopulation worker pool floor (read directly by the binary)max(NUM_WORKERS, 2)
PGCACHE_POPULATION_WORKERS_MAXPopulation worker pool ceiling (read directly by the binary)NUM_WORKERS × 8
PGCACHE_TELEMETRYSet to off to disable anonymous telemetry reporting—
PGCACHE_TLS_CERTBase64-encoded TLS certificate—
PGCACHE_TLS_KEYBase64-encoded TLS private key—

Docker Examples

Basic:

docker run -d -p 5432:5432 pgcache/pgcache \
  --upstream postgres://user@db:5432/myapp

With replication override (origin behind PgBouncer):

docker run -d -p 5432:5432 pgcache/pgcache \
  --upstream postgres://user@pgbouncer:6432/myapp \
  --replication-host db-direct.example.com \
  --replication-port 5432

With environment variables:

docker run -d -p 5432:5432 \
  -e UPSTREAM_URL=postgres://user@db:5432/myapp \
  -e NUM_WORKERS=8 \
  -e REPLICATION_HOST=db-direct.example.com \
  pgcache/pgcache

With individual origin fields (avoids URL-encoding credentials with special characters):

docker run -d -p 5432:5432 \
  -e ORIGIN_HOST=db.example.com \
  -e ORIGIN_DATABASE=myapp \
  -e ORIGIN_USER=app_user \
  -e ORIGIN_PASSWORD='p@ss/w:rd' \
  -e ORIGIN_SSL_MODE=require \
  pgcache/pgcache

With a mounted TOML config file:

docker run -d -p 5432:5432 -p 9090:9090 \
  -v ./pgcache.toml:/etc/pgcache/config.toml:ro \
  -e CONFIG_FILE=/etc/pgcache/config.toml \
  pgcache/pgcache

With table allowlist and pinned tables:

docker run -d -p 5432:5432 \
  -e UPSTREAM_URL=postgres://user@db:5432/myapp \
  -e ALLOWED_TABLES=users,orders,products \
  -e PINNED_TABLES=users,products \
  pgcache/pgcache

With pinned queries:

docker run -d -p 5432:5432 pgcache/pgcache \
  --upstream postgres://user@db:5432/myapp \
  --pinned-queries "SELECT * FROM config;SELECT * FROM lookup"