pgBadger 13.3 landed on November 3, 2026,[1] and it is one of those quiet maintenance releases that is worth paying attention to if you run PostgreSQL on your own VPS. Why now, specifically? PostgreSQL 19 general availability is planned for November 19, 2026,[4] which gives you a two-week window to do something most people skip before a major upgrade: look at what your current instance is actually doing. The logs PostgreSQL already writes are the highest-signal dataset on your box - no agents, no extra daemon, just the truth about slow queries, errors and disk spills. pgBadger turns that raw log stream into a single self-contained HTML report you can open in a browser.
This guide covers the full loop on Debian or Ubuntu: what is new in 13.3, installing it, configuring PostgreSQL to log what pgBadger needs, running reports by hand and by cron, and reading the sections that matter.
What pgBadger is, in one paragraph
pgBadger is a PostgreSQL log analyzer built for speed, producing detailed HTML5 reports from PostgreSQL log files.[1] Practical details that matter on a small box:[3]
- It is a single standalone Perl script. No Perl modules, no database extensions, no agent to deploy. Charts are drawn by an embedded JavaScript library (flotr2), so the only runtime requirement your machine needs is a modern Perl distribution and your browser does the rest.[3]
- It autodetects the log format (stderr, syslog, csvlog, jsonlog) and reads compressed files directly - gzip, bzip2, lz4, xz, zip and zstd are all supported, with the decompression utility detected from the file extension.[3]
- It parallelizes parsing across cores with
-j N, which matters when you feed it a month of logs from a busy instance.[3] - Reports are zoomed and saved as PNG from the browser, so you can drop a chart into a ticket or a post-mortem.[3]
The author, Gilles Darold, also wrote ora2pg, PostgreSQL’s standard migration tool.[1] pgBadger has been around since 2012 and is distributed under the PostgreSQL License.[3]
What’s new in 13.3
13.3 is a maintenance release - bug fixes and applied patches reported since the previous release, no new headline features.[1] But the fix list is unusually relevant to production use, which is exactly when a fix release is worth the upgrade:
auto_explaindouble counting is fixed. An execution reported by bothlog_min_duration_statementandauto_explainwas counted twice; 13.3 deduplicates it.[1][2] If you runauto_explainon any instance, your “top queries” were inflated before this release.--explode(one report per database) got a round of fixes: retention (-R) now applies to per-database HTML reports, database names are sanitized before being used as paths, and the incremental calendar no longer comes out empty.[2]- Watch mode filters remote logs on the remote host instead of transferring everything, which makes
-wover SSH cheaper on big installations.[1][2] - Multiline statement handling was fixed in several places - continuation lines in prepared queries, queries split between temporary files and query reports.[2]
- Concurrent runs are now safe by default: temporary db-list and last-parsed files get per-run names, so two pgBadger processes can’t read the same files under a cron overlap.[1][2]
- Smaller but useful:
--dbuserand user filtering no longer drop valid queries, “Query Parameters: …” lines fromauto_explainplans are handled, and there’s a copy of the explain plan.[1][2]
If any of that describes your setup - and auto_explain plus cron-covered incremental reports describes most production boxes - 13.3 is the version to be on.
Installing pgBadger on Debian or Ubuntu
There are two routes. Debian and Ubuntu both package pgBadger (apt install pgbadger),[6] which is fine if the packaged version satisfies you. For the current 13.3 release, the documented path is the GitHub tarball:[3]
# 1. grab the release tarball (current: v13.3)
wget https://github.com/darold/pgbadger/archive/refs/tags/v13.3.tar.gz
tar xzf v13.3.tar.gz
cd pgbadger-13.3/
# 2. build and install - this puts pgbadger in /usr/local/bin by default
perl Makefile.PL
make
sudo make install
By default the script lands in /usr/local/bin/pgbadger and the man page in /usr/local/share/man/man1/pgbadger.1.[3] If you are on an RPM-based distro or want Debian-style layout, pass INSTALLDIRS=vendor to Makefile.PL, which is what Debian itself uses.[3] Verify the install:
pgbadger -V
# pgBadger version 13.3
Configure PostgreSQL to produce logs pgBadger can eat
PostgreSQL on Debian and Ubuntu logs to stderr out of the box, but without the logging collector: the pg_ctlcluster wrapper redirects the server’s stderr into one file per cluster, /var/log/postgresql/postgresql-<version>-<cluster>.log,[7] and the default config logs almost nothing useful for analysis. log_destination defaults to stderr, and logging_collector is the background process that captures those stderr messages into rotated log files; its log_directory defaults to log inside the data directory, so set it explicitly if you want the files to stay in /var/log/postgresql/.[5] You then need to say what gets logged. The following block is the pgBadger-recommended core:[3]
# postgresql.conf - the logging block pgBadger needs
log_destination = 'stderr'
logging_collector = on
# keep collector files next to the Debian/Ubuntu default log
log_directory = '/var/log/postgresql'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
# slow query logging: 0 logs every statement, 1000 only those taking >= 1s
log_min_duration_statement = 1000
# at minimum a time (%t, %m or %n) and a process (%p or %c) escape
# the extended version below powers per-user/db/app/client reports
log_line_prefix = '%t [%p]: user=%u,db=%d,app=%a,client=%h '
log_checkpoints = on
log_connections = on
log_disconnections = on
log_lock_waits = on
log_temp_files = 0
log_autovacuum_min_duration = 0
log_error_verbosity = default
Three tripwires worth spelling out:
- Don’t set
log_statement = 'all'. pgBadger does not parse that output, and worse, whenlog_statementisall, nothing is logged throughlog_min_duration_statementat all.[3]log_min_duration_statementis the knob you want; keep it at 0 to log every statement, or raise it on a busy server to log only slow ones.[3] log_line_prefixmust contain a time and a process escape. The exact format beyond that is free-form - pgBadger supports any custom prefix as long as%t/%m/%nand%p/%care present.[3] The example above is the documented stderr format that unlocks the user, database, application and client breakdowns in the report.- Log messages must be in English. The parser only supports English output, so keep
lc_messagesat'C'or'en_US.UTF-8'- a French or Russian locale will produce reports with empty or garbled text.[3] If you changed it for another reason, this is the setting to restore.
After editing, reload (config-only) or restart, then confirm lines are appearing:
sudo systemctl reload postgresql # or: sudo systemctl restart postgresql
# recent log lines should show durations, connections, checkpoints, etc.
sudo tail -n 50 /var/log/postgresql/postgresql-*.log
log_temp_files = 0 is important: without it, pgBadger has no data for the temporary files report, which is one of the most useful sections on a memory-constrained VPS (more below).
Generate your first report
Point pgBadger at the captured logs. It accepts a file, a list of files, a glob, or - for stdin:[3]
# latest log file (or the rotated ones)
pgbadger /var/log/postgresql/postgresql-2026-11-07_000000.log -o /var/www/pg_reports/weekly.html
# a whole rotation batch, including compressed history
pgbadger /var/log/postgresql/postgresql-*.log* -o /var/www/pg_reports/monthly.html
# use all your cores on a huge file
pgbadger -j 8 /var/log/postgresql/postgresql-*.log* -o report.html
# errors only, in "watch" mode
pgbadger -q -w /var/log/postgresql/postgresql-*.log* -o /var/www/pg_reports/errors.html
The output is one self-contained HTML file with everything embedded - you can scp it anywhere or serve it with your existing nginx setup (our nginx reverse proxy guide covers serving it safely if you want it on the web).
A first run is also the moment to sanity-check detection: if the report looks empty or garbled, force the format with -f stderr (or -f syslog, csvlog, jsonlog), and re-check the log_line_prefix advice above.[3]
Run it like a boring cron job
The README’s cron examples are the canonical pattern, and they are the two shapes you’ll use most:[3] (/usr/bin/pgbadger is the apt-package path; after the tarball install the script is in /usr/local/bin/pgbadger - put whatever command -v pgbadger prints into the crontab.)
Weekly error digest - every Monday at 23:30, an errors-only letter:
30 23 * * 1 /usr/bin/pgbadger -q -w /var/log/postgresql/postgresql-*.log* -o /var/www/pg_reports/pg_errors.html
Incremental reports - every day at 04:00, one report per day plus a cumulative report per week:
0 4 * * * /usr/bin/pgbadger -I -q /var/log/postgresql/postgresql-*.log* -O /var/www/pg_reports/
In incremental mode (-I) pgBadger writes binary data files and regenerates the HTML on each run; --retention N keeps the last N weeks and removes older day and week directories automatically, which keeps disk usage bounded without you touching it.[3] This is also the mode where the 13.3 concurrency fix matters: if a run takes longer than the cron interval, a naive overlap previously meant two processes racing over the same temp files - 13.3’s per-run names turn that into a non-event.[1][2]
One cron-specific gotcha: % has meaning in cron. If your command contains date +%F-style substitutions, escape them or pull them into a small wrapper script.[3]
Reading the report: the sections that matter
pgBadger generates a lot of charts; on a self-hosted box, five sections carry almost all the value.[3]
Overall statistics. The summary line tells you the analysis window, and bars for queries, connections and errors per hour give you the shape of the day at a glance. An hourly error spike at 03:14 that matches your cron backups is often the whole story.
Top slow queries and most time-consuming queries. This is the report’s centerpiece: normalized queries sorted by total duration, with count, average, and a histogram of execution times per query.[3] Don’t judge by a single slow outlier - sort by total time. On an OLTP VPS the queries that hurt are the ones you call ten thousand times a day at 50 ms each, not the one-off 5-second report you run at night.
Temporary files. With log_temp_files = 0 enabled, you get reports of queries that generated the most and the largest temporary files.[3] Each spill past work_mem writes to disk, and on a VPS with a burstable SSD this is where “fine in dev, weirdly slow in prod” comes from. If a query shows up here, work_mem or the query plan is the conversation to have.
Error report, including deadlocks. Every panic, fatal, error and warning event is collected and classified, with a per-error timeline.[3] Deadlock-detected errors land here automatically - PostgreSQL logs a deadlock the moment it resolves one, and pgBadger surfaces the message, so a recurring deadlock detected entry in the error chart tells you application-level lock ordering needs work rather than server tuning. Watch mode (-w) is the errors-only version of this, designed to be your Monday-morning letter.[3]
Autovacuum and autoanalyze. With log_autovacuum_min_duration = 0 you see every autovacuum and autoanalyze run per table, including how long each took.[3] A table with a huge, repeatedly logged vacuum is a bloat or config problem in the making - and bloat is precisely the thing the 19 release addresses. PostgreSQL 19 introduces REPACK, the successor to VACUUM FULL, and if your pre-upgrade report already shows a problem table, that’s the exact table to repack after you migrate (see our PostgreSQL 19 upgrade guide for the full plan).
The PG19 angle: baseline now, compare after
Here is the concrete workflow that makes this release timing useful. PG19 GA is planned for November 19, 2026.[4] Two weeks before it lands:
- Set up the config block above and let it collect for at least one full business day; don’t analyze a Tuesday against a Sunday report.
- Generate a full incremental report at
-I, and keep the output directory. - After the upgrade to 19, regenerate the same report and diff the top-20 slowest queries, the temporary files section, and the autovacuum table.
An upgrade that keeps your query plans but halves your temp file time is a success you can point at; an upgrade that shifts a query from 10th to 2nd place on the slow list is a regression you catch on day one instead of at the next incident. Either way you’re working from your own measurements, not vibes.
Wrap-up
pgBadger 13.3 is a maintenance release with a production-shaped fix list: correct auto_explain totals, safe concurrent runs, and a cleaned-up --explode path.[1][2] On a Debian or Ubuntu VPS you can go from zero to a readable weekly report in about fifteen minutes: install the tarball, flip the logging block, add one cron line. Then, before November 19, run the baseline you’ll compare against after the PostgreSQL 19 upgrade.[4] Your future self, doing that upgrade at 11pm, will thank you.
Sources
- PostgreSQL News - pgbadger v13.3 has been released (2026-11-03). https://www.postgresql.org/about/news/pgbadger-v133-has-been-released-3435/ - checked 2026-11-07
- GitHub - darold/pgbadger releases: Version 13.3 (2026-11-03). https://github.com/darold/pgbadger/releases/tag/v13.3 - checked 2026-11-07
- GitHub - darold/pgbadger README (installation, PostgreSQL configuration, options, incremental reports). https://github.com/darold/pgbadger - checked 2026-11-07
- PostgreSQL News - PostgreSQL 19 RC 1 Released! (2026-10-15; GA planned for 2026-11-19). https://www.postgresql.org/about/news/postgresql-19-rc-1-released-3409/ - checked 2026-11-07
- PostgreSQL Documentation 18 - Error Reporting and Logging (log_destination, logging_collector, log_min_duration_statement). https://www.postgresql.org/docs/current/runtime-config-logging.html - checked 2026-11-07
- Debian Packages - package pgbadger. https://packages.debian.org/search?keywords=pgbadger - checked 2026-11-07
- Debian - pg_ctlcluster(1), postgresql-common (start: per-cluster log file, by default /var/log/postgresql/postgresql-
- .log). https://manpages.debian.org/testing/postgresql-common/pg_ctlcluster.1.en.html - checked 2026-11-07