Documentation Semantics: Durability Guarantees of the Logging Collector
Core Problem
A first-time contributor (Daniel) raised a documentation clarity issue that sits at an interesting intersection of PostgreSQL's architecture and user expectations: the relationship between transaction commit semantics (ACID) and server log output. Users — particularly those using log_statement or the logging collector for audit, security, or compliance purposes — may incorrectly assume that server logs form a consistent record of committed work, when in fact the logging subsystem is entirely outside the WAL/MVCC guarantees.
Two specific mismatches between user expectation and implementation exist:
-
Temporal ordering vs. commit state: In
exec_simple_query()(src/backend/tcop/postgres.c around line 1070),log_statementfires after parse analysis but before execution. A logged statement may subsequently error out, be rolled back, or have its effects lost due to a crash before commit. Conversely, for the extended query protocol, the log entry is emitted on receipt of the Execute message, again before the transaction outcome is known. -
Durability of the log file itself: The log write path (
ereport→errfinish→EmitErrorReport→send_message_to_server_log→write_syslogger_file) deliberately does not fsync, andwrite_syslogger_filein syslogger.c handles write errors by falling back to stderr rather than raising an error that would abort the transaction. This is a conscious design choice — crashing the server because the log disk is full would be "overly harsh" — but it means a committed transaction can have no corresponding log record on disk after a power loss.
The Design Tension
This is not a bug; it is a deliberate architectural separation. Integrating server logging into the WAL would be both a massive layering violation and a severe performance penalty (synchronous fsync on every logged statement). Logging is intentionally a best-effort side channel, not a transactional artifact. The question is purely one of documentation: should this separation be made explicit for users who might otherwise rely on logs as an audit trail?
Bruce Momjian's initial pushback ("Why do you think log_statement is best effort?") and subsequent comments reflect a reluctance to adopt the phrase "best effort" — which carries connotations of flakiness — when the actual behavior is well-defined: log on entry, regardless of outcome. David Johnston reinforced this by noting that a SELECT returning rows to a client is worth logging even if its enclosing transaction rolls back; tying log emission to commit status would be "an insane design choice" and would also break use cases like debugging failed transactions.
Bruce's pointer to log_min_duration_statement=0 is technically significant: that parameter logs after statement completion, so it does provide a closer (though still not commit-synchronized) approximation of "statements that actually ran to completion." This is a useful distinction for users who care about post-hoc correlation.
Evolution of the Proposed Patch
Daniel's proposal migrated based on feedback:
- Initial location: A note on
log_statementwarning that "not all committed statements will be logged." - Reframing after pushback: The inverse framing — "logged statements may not have been committed" — which is the actually correct statement about the pre-execution logging order.
- Final location (May 2026 patch): Moved to the
logging_collectorsection, reframed around durability of the log file rather than transaction semantics. This is arguably the better architectural home: the collector is the component responsible for getting log bytes to disk, and its durability guarantees (or lack thereof) are a property of that component, not oflog_statement.
The patch also questioned the existing wording "The logging collector is designed to never lose messages" — which, taken literally, overstates the guarantee. The collector's actual invariant is that it applies backpressure (blocking writers via pipe semantics) rather than dropping messages in-memory under load, unlike syslog's rate-limiting behavior. It makes no promise about post-crash durability.
Fujii Masao's Refinement
Fujii Masao (committer) provided the key wording improvements that tighten the semantics:
-
For the "never lose messages" claim, he proposed: "The logging collector is designed to avoid dropping messages even under very high log volume." This correctly scopes the guarantee to the in-memory/backpressure behavior that distinguishes it from syslog, without making durability claims.
-
For the durability caveat, he rejected "writes to disk asynchronously" as ambiguous (it could be read as referring to OS-level write buffering, or to the collector's async pipe architecture) and proposed: "The logging collector does not guarantee that log messages have reached durable storage. A system crash, power loss, or an error while writing the log file can still result in messages being lost." This is precise: it names the failure modes (crash, power loss, write error) and the consequence (message loss) without overcommitting on mechanism.
Key Technical Insights
- The logging collector's backpressure model is distinct from syslog's drop-under-load model. This is a real engineering property worth documenting, and the current docs obscure it with the overly strong "never lose messages" phrase.
- The error-handling policy in
write_syslogger_file(log-to-stderr-and-continue) is the specific code path that makes log durability best-effort. Daniel correctly traced this throughelog.candsyslogger.c. - The extended query protocol logs at Execute-message receipt (David's "definitive" sentence) — this is the user-facing commitment about when logging happens, and is more precise than the parse-error sentence Daniel initially cited.
- There is a latent UX issue: users reaching for
log_statementfor audit purposes should likely be directed to pgaudit or tolog_min_duration_statement=0if they want post-execution logging, though neither provides WAL-level durability either.
Participant Dynamics
Bruce Momjian and David Johnston initially pushed back on the framing — not the underlying observation. Their resistance to "best effort" language is substantive: the term is imprecise and implies unreliability rather than a clean architectural boundary. Once Daniel refocused on durability (a concrete, demonstrable property) and moved the documentation to the logging_collector section, the objection dissolved.
Fujii Masao's endorsement as a committer, along with his concrete wording suggestions, effectively moves the patch toward a committable form. His refinements show the typical committer-level attention to exactly what is being guaranteed and what is not — avoiding both overclaiming and vagueness.