Chapter 02 · Cluster Architecture, Processes, Memory, Files, and Configuration

Logging Collector, Structured Logs, Startup Diagnostics, and a Baseline Production Profile

Turn PostgreSQL logs into operational evidence: choose destinations and structured formats, correlate messages with sessions, validate configuration before change, diagnose a harmless startup failure, and record a minimal baseline profile.

Intermediate → Advanced110–140 minutesLogging + startup-diagnostics labCurrent patched PostgreSQL 18.xstderr/csvlog/jsonlog + platform notesLast reviewed: August 2026

Learning outcomes

A database that cannot explain its own failures is expensive to operate. PostgreSQL logs can answer connection, startup, checkpoint, autovacuum, query, replication, and background-worker questions—but only if destinations, formats, verbosity, and correlation fields are configured intentionally. Logging too little hides incidents; logging everything can expose sensitive data, consume disk, and overwhelm analysis.

01

Distinguish stderr, csvlog, jsonlog, syslog, and Windows eventlog destinations, including when the logging collector is required.

02

Use log_line_prefix or structured fields to correlate server messages with PID, session, role, database, application name, and client identity.

03

Locate current log files when the built-in collector owns them and understand platform/package differences.

04

Validate configuration files, inject one harmless failure in the disposable lab, recover from evidence, and distinguish reload failures from startup failures.

05

Record a minimal baseline profile without turning one machine’s values into universal tuning advice.

1. Where PostgreSQL can send logs

log_destination accepts one or more supported destinations. Core PostgreSQL supports stderr, csvlog, jsonlog, and syslog; Windows also supports eventlog. The default is commonly stderr. Whether stderr ultimately appears in a file, system journal, container log, service manager, or terminal depends on how PostgreSQL was started.

Destination Strength Operational caveat
stderr Simple, universal PostgreSQL output stream. Final storage/rotation depends on collector, service manager, container runtime, or redirection.
csvlog Structured columns suitable for machine ingestion. Requires logging_collector for CSV files.
jsonlog Structured JSON fields including session/process metadata. Requires logging_collector for JSON files; consumers must tolerate future extra fields.
syslog Integrates with Unix system logging. System syslog daemon must be configured to retain/route PostgreSQL messages.
eventlog Windows Event Log integration. Windows-specific setup and source registration considerations apply.
sql · inspect current logging destinations
SELECT name, setting, context, source, pending_restartFROM pg_catalog.pg_settingsWHERE name IN ('log_destination','logging_collector','log_directory','log_filename')ORDER BY name;

2. The logging collector changes who owns stderr files

When logging_collector is enabled, PostgreSQL starts a logger process that captures stderr and redirects messages into files according to logging configuration. Because logging_collector is a server-start parameter, enabling/disabling it requires restart. CSV and JSON file destinations depend on the collector.

When the collector is managing stderr/csvlog/jsonlog files, PostgreSQL maintains a current_logfiles file that records the active log-file paths. That is safer than guessing a timestamped filename.

sql · server-side location evidence
SHOW data_directory;SHOW logging_collector;SHOW log_directory;SHOW log_filename;SHOW log_destination;

The SQL settings tell you configuration, not the contents of current_logfiles. Reading the file requires server filesystem access under appropriate OS permissions. In containerized labs, prefer docker logs when stderr is owned by the runtime unless you deliberately enable file collection.

3. Correlation: a log line must identify the session behind it

Plain stderr text can be made much more useful with log_line_prefix. Useful escapes can include timestamp, PID, session identifier, user, database, remote host, application name, and more. Structured jsonlog already emits named fields such as timestamp, user, dbname, pid, remote_host, session_id, and session_start.

For a human-readable stderr baseline, a prefix conceptually like the following is useful:

text · example correlation-oriented prefix
# Example only; verify escapes in the PostgreSQL 18 logging docs.log_line_prefix = '%m [%p] %c %u@%d app=%a client=%r '

Do not copy prefixes blindly into production. Every extra field increases log volume, and some identifiers may be sensitive. The goal is enough correlation to join a log event back to pg_stat_activity, application telemetry, or an incident timeline.

4. Choose what to log: diagnostic value versus cost and exposure

PostgreSQL offers many event/threshold settings: connection/disconnection logging, statement duration thresholds, lock waits, checkpoints, temporary files, autovacuum details, and more. Logging all SQL statements can expose credentials embedded incorrectly in SQL, personal data, or large payloads. It also produces significant I/O.

sql · inspect a conservative diagnostic subset
SELECT name, setting, unit, context, sourceFROM pg_catalog.pg_settingsWHERE name IN (  'log_connections',  'log_disconnections',  'log_min_duration_statement',  'log_lock_waits',  'deadlock_timeout',  'log_checkpoints',  'log_temp_files')ORDER BY name;

A baseline should answer specific operational questions. For example: can I correlate a failed login to client/application identity? Can I see a statement that exceeds the SLO threshold? Can I detect lock waits or temp-file spills? Can I explain checkpoint-related write activity? The correct thresholds vary by system.

5. Structured logging with jsonlog

PostgreSQL’s JSON log format is useful when logs are ingested into structured search/analytics systems. Each line is a JSON object with named keys. Consumers should ignore unknown fields so new PostgreSQL versions can add fields without breaking ingestion.

A disposable file-collector setup might use:

text · illustrative structured-log configuration
logging_collector = onlog_destination = 'stderr,jsonlog'log_directory = 'log'log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'

logging_collector requires restart. log_destination is a configuration setting whose context should be verified on the target server. Before applying any change, query pg_settings.context and validate file syntax with pg_file_settings.

6. Startup diagnosis: use evidence before editing randomly

A startup failure has a different diagnostic path from a reload problem. If PostgreSQL is not running, you cannot query pg_settings from that instance. You need service-manager/container stderr, PostgreSQL log output, or direct pg_ctl/postgres startup diagnostics for the disposable cluster.

Before restart, however, a running instance can often detect configuration-file problems:

sql · preflight configuration files
SELECT sourcefile, sourceline, name, setting, applied, errorFROM pg_catalog.pg_file_settingsWHERE error IS NOT NULL   OR name IN ('logging_collector','log_destination','log_line_prefix')ORDER BY sourcefile, sourceline;SELECT pg_reload_conf();

If a reload encounters an invalid value, PostgreSQL logs the problem and keeps the previous effective setting where appropriate. A full startup can fail when critical configuration is invalid. That is why preflight and rollback copies matter.

7. Harmless failure injection: invalid port in an isolated restart rehearsal

For a restart-oriented exercise, use a separate disposable cluster or container, not the only Chapter 01 lab you care about. A simple failure is to set an invalid value for a startup parameter such as port or add an unrecognized parameter name, then observe startup failure and restore the file.

Safer alternative

If you are not comfortable stopping/restarting your lab, do not inject a startup failure. Instead add an invalid line to an included file, query pg_file_settings while the server is still running, then remove it before any restart. You still learn syntax diagnosis without availability impact.

text · intentionally invalid configuration example
# Disposable cluster only. This is intentionally invalid.port = 'not-a-number'

Expected evidence is a parse/value error naming the parameter/file/line. The repair procedure is: preserve the error message, restore the known-good configuration, validate again, start/reload as appropriate, and verify from SQL. Do not keep trying random edits until it “starts somehow.”

8. A baseline production profile is a record, not a tuning prescription

At the end of Chapter 02, capture the configuration and identity facts future lessons depend on. Store the output with the lab notes, excluding secrets.

sql · ServiceHub Chapter 02 baseline snapshot
SELECT version() AS server_version;SELECT current_database(), current_user, pg_backend_pid();SHOW data_directory;SHOW config_file;SHOW hba_file;SHOW server_encoding;SHOW TimeZone;SELECT name, setting, unit, context, source, pending_restartFROM pg_catalog.pg_settingsWHERE name IN (  'port','listen_addresses','max_connections',  'shared_buffers','wal_buffers','work_mem','maintenance_work_mem',  'logging_collector','log_destination','log_line_prefix',  'log_min_duration_statement','log_lock_waits','log_temp_files')ORDER BY name;

Add host/container memory limit, PostgreSQL package/image identity, psql version, storage location, and whether the instance is disposable. Do not store passwords or secret-bearing connection strings in the baseline file.

9. Deliberately wrong approach: enable log_statement = 'all' everywhere

When debugging one incident, an operator may enable full statement logging globally and forget it. This can multiply log volume, expose sensitive literal values, increase I/O, and make important events harder to find. The repair is to define the question first, use the narrowest logging mechanism and duration that answers it, protect log access, and revert temporary diagnostics.

For slow-query diagnosis, a duration threshold or targeted extension/observability strategy is often more appropriate than permanent full statement logging. Later observability chapters add pg_stat_statements and workload-level evidence.

10. Hands-on lab: produce and correlate one diagnostic event

  1. Set a distinct application_name=bda_ch02_l5 on an administrator lab session.
  2. Record pg_backend_pid(), role, database, and current logging settings.
  3. Choose a safe session-visible event: for example trigger statement_timeout on pg_sleep or deliberately reference a nonexistent table.
  4. Locate the corresponding server log event using the platform’s actual logging path: collector file, Docker logs, system journal, or Windows Event Viewer as applicable.
  5. Correlate the event to PID/application/session fields available in your format.
  6. Record what the log proves and what it does not prove.
sql · generate a controlled error with correlation metadata
SET application_name = 'bda_ch02_l5';SELECT pg_backend_pid(), current_user, current_database();SET statement_timeout = '1s';SELECT pg_sleep(3);RESET statement_timeout;

Check your understanding

  1. When is logging_collector required for csvlog/jsonlog files?
  2. Why should log consumers tolerate unknown JSON fields?
  3. What is the difference between a reload failure and a startup failure from a diagnostic perspective?
  4. Why can full statement logging be a security and performance problem?
  5. What belongs in a baseline profile, and what must not be stored there?
Review the answers

The built-in collector is required to generate CSV/JSON log files. JSON consumers should ignore unknown keys because future versions can add fields. During reload, the server is still running and can expose file/effective state plus logs; during failed startup you must rely on startup/service/container/log evidence until the instance runs again. Full statement logging can leak literal data and generate heavy I/O. A baseline should capture versions, paths, contexts, non-secret settings, resource limits, and topology facts—never passwords or secret connection strings.

11. Chapter 02 summary and bridge to Chapter 03

You can now observe a PostgreSQL instance as a living system. Connections become dedicated backend processes; auxiliary processes carry instance-wide responsibilities; PGDATA and configuration files have defined ownership and precedence; memory is a concurrency budget rather than a percentage ritual; GUC values have source, scope, context, and lifetime; and logs can correlate failure evidence back to sessions.

Chapter 03 moves from instance-wide architecture to PostgreSQL’s namespace and ownership model: cluster versus database versus schema boundaries, search_path, roles, catalogs, dependencies, and multi-team privilege design.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only assets compatible with the Ethereum/ERC-20 network. Do not send TRC-20/TRON assets.