max_active_replication_origins is a ten-year-old XXX comment that finally got paid off. It arrived in PostgreSQL 18, and it exists because the thing it controls had been borrowing another parameter’s number since 9.5. On 14 through 17, the number of replication origins a subscriber can track is set by max_replication_slots, a parameter whose real job is on the publisher; from
maintenance_work_mem is the memory parameter that behaves the way people wrongly assume work_mem does: one allocation, for one operation, in one session, and the number you set is the number that gets used. work_mem is a per-sort, per-hash, per-worker allowance that a single query can claim a dozen times over. maintenance_work_mem is a ceiling. The docs say it is “safe
maintenance_io_concurrency is effective_io_concurrency for work the documentation describes as done “on behalf of many client sessions.” That phrase is the entire design rationale: a VACUUM is paying down I/O debt that every session ran up, so it can reasonably be more aggressive about read-ahead than any one of them would be. Mechanically the two parameters are the same knob, including
logical_decoding_work_mem is how much of somebody else’s uncommitted transaction a walsender will hold in memory before it starts writing that transaction to disk a second time.
The name suggests a cousin of work_mem; the mechanism is closer to a swap file. Logical decoding reads WAL and reassembles the records into per-transaction change lists, in a structure called the
These are the oldest logging parameters PostgreSQL still ships, and the output looks it. Each is a boolean, off by default, superuser context, and each makes the backend call getrusage() before and after one stage of running a statement and write the difference to the log at LOG level. log_parser_stats covers the parser, parse analysis, and the rewriter (three blocks
These two parameters answer the same question about the same process: what is the startup process doing, and why is it not done? The startup process is the backend that replays WAL. On a primary it exists only during crash recovery, and while it exists nothing else can connect; a client gets FATAL: the database system is not yet accepting
log_lock_waits is the cheapest lock-contention detector PostgreSQL ships, and through version 18 it is off by default. Turn it on. PostgreSQL 19 will do it for you.
The mechanism is borrowed rather than built. When a backend has to sleep on a heavyweight lock (a row, a relation, a transaction ID, an advisory lock), it arms a timer for
log_replication_commands is log_statement = all for walsenders, with the one difference that you should turn it on.
A replication connection (replication=1 for physical, replication=database for logical) speaks a small language of its own: IDENTIFY_SYSTEM, CREATE_REPLICATION_SLOT, START_REPLICATION, BASE_BACKUP, DROP_REPLICATION_SLOT, and a few others. log_statement never sees them. This parameter does, and writes each one
Last time ended with log_min_duration_statement set to a threshold you would actually investigate. The cost of that threshold is that everything below it is invisible, and the queries below it are frequently the story: one query that runs for a minute is a problem you can see, but twenty million queries at a millisecond each are five and a half
Every other statement-logging parameter in this cluster decides whether a query goes into the log. These two decide whether your users’ data goes with it.
Under the extended query protocol the statement text arrives with $1, $2 placeholders and the values arrive separately, in the Bind message; those values are the bind parameters. When log_statement, log_min_duration_statement