Postgres Tooling News: pgrecon, BackupDrill, DBtune 4.0
Three PostgreSQL projects published release news on the same day this week, and they share more than a date. pgrecon 0.7.3 inventories an Oracle schema before anyone commits to a migration. BackupDrill turns “did the backup actually restore?” into a scheduled job that produces evidence. DBtune 4.0 pushes its tuning advice out of server parameters and into indexes and autovacuum.
None of that is a headline feature, which is the point. All three automate the audit work DBAs postpone because it shows no visible progress: the pre-migration inventory, the untested restore, the index review nobody scheduled. PostgreSQL 19 is in release candidate with GA slated for November 19; the core is what everyone watches, but this quarter’s wins are landing one layer up.
pgrecon 0.7.3: Oracle migration math before you commit
Oracle-to-Postgres migrations fail late on a predictable list of things: package-level state, autonomous transactions, LONG columns, interval partitioning, database links. pgrecon, Apache-2.0 and newly public at 0.7.3 (posted 22 October), exists to name those before the project gets a budget.
The design choice worth stealing: it never connects to either database. pgrecon emits a read-only SQL*Plus script that your DBA reviews and runs; only the dump folder crosses the boundary, and it becomes a local SQLite inventory. A deterministic rule engine runs 80 rules over it — data types and length semantics, storage and partitioning, PL/SQL parsed with a full grammar rather than pattern matching, supplied packages such as UTL_FILE and DBMS_LOB, schema objects, optimizer hints. Findings carry a stable rule id, a severity and line-level evidence; pgrecon explain R-PKG-01 prints the write-up and which extension helps (orafce, pgtt).
The converter is deliberately narrow: PostgreSQL DDL for what it can prove — native partition children, constraints, indexes, CONNECT BY folded into WITH RECURSIVE, ROWNUM top-N as LIMIT, MERGE — and a named residue line for each object it refuses, with the line number. Packages, autonomous transactions, REF CURSOR interfaces and BULK COLLECT are refused by name rather than guessed at. That residue file is the real deliverable: your porting backlog, itemised.
pgrecon script --source-version 19
sqlplus readonly_user@service @pgrecon_extract.sql APP_SCHEMA
pgrecon load dump_dir --db inventory.db
pgrecon report --db inventory.db --remedies
pgrecon estimate --db inventory.db
pgrecon convert --db inventory.db
On the bundled sample schema, estimate returned a low / expected / high range of 106 / 131 / 180 person-days, with the components and assumptions printed behind each figure. Treat that as a scoping instrument, not a quote: the project is alpha, the rule catalogue is still growing, and the code lane converts only what it can prove.
BackupDrill: a restore you never tested is a hope
Backups are the easiest part of the stack to be confidently wrong about. The announcement says it plainly: most teams find out whether their pg_dump archives work on the day they need them.
BackupDrill runs pg_dump in custom format against a Supabase project, streams the archive to an S3-compatible bucket you own (S3, R2, B2, Wasabi) with a checksummed manifest, then backupdrill drill restores the latest snapshot into a throwaway PostgreSQL container. The drill checks more than an exit code: archive checksum, that pg_restore completed, that post-data objects such as indexes, constraints and triggers were created, that every table is present, that tables which held data are not empty — and it records the restore duration. That output is the audit evidence a restore drill is supposed to produce.
npm install -g backupdrill
export BACKUPDRILL_DATABASE_URL="postgresql://postgres.<ref>:...@<pooler-host>:5432/postgres"
export BACKUPDRILL_S3_BUCKET="my-backups"
backupdrill backup # pg_dump to your bucket + manifest
backupdrill drill # restore latest into a throwaway container
backupdrill drill --check-cmd "npm run smoke" # app-level check on the restored copy
Two constraints before you schedule it. It targets Supabase-hosted Postgres only for now (15 through 17), and egress is billed: $0.09/GB of uncached egress above your plan allowance, with Spend Cap on by default — which throttles the project’s egress and fails the backup rather than billing the overage. A daily dump of a large database is a budget line, not a free cron. The archives are plain pg_dump, so if you are doing restores by hand today, our pg_dump and pg_restore walkthrough is the baseline.
DBtune 4.0: index advice with the write bill attached
DBtune 4.0 (announced 6 October) is the commercial entry here, and the most interesting thing about it is what it refuses to do. The release moves beyond server parameter tuning into index optimization and autovacuum monitoring, ranking opportunities by total_exec_time — a 200 ms query called ten thousand times an hour outranks a 30-second nightly report.
Analysis runs against a statistical snapshot of your workload, using PostgreSQL’s own planner plus HypoPG to test hypothetical indexes. No extension beyond pg_stat_statements is needed and no queries are executed against your database. Each recommendation lists columns, INCLUDE columns, any WHERE clause, estimated disk size, estimated write cost per day, the queries it helps, and paste-ready DDL. Existing indexes are bucketed into Attention, Informational and Healthy: unused for seven days is informational, 28 days escalates to a drop candidate with reclaimable bytes quoted, redundant narrower indexes are flagged, and constraint-backing indexes are never proposed for removal.
Recommendations are not applied automatically — you run the DDL. That is the right default, because no advisor knows your write amplification budget. One prerequisite catches people out: if logic runs through procedures, functions or DO blocks, set pg_stat_statements.track = 'all', or only the outer CALL is recorded and the inner queries stay invisible.
ALTER SYSTEM SET pg_stat_statements.track = 'all';
SELECT pg_reload_conf();
Also on the wire
CloudNativePG recipe 28 covers generated and rotating Postgres user passwords (24 October): a DatabaseRole generating its own password, storing it in an operator-owned Secret, shaping it with criteria and rotating on a schedule, with PostgreSQL enforcing the lifetime through VALID UNTIL. The feature is merged but unreleased; it lands in 1.31 this quarter.
What this means for Houston teams
- Energy, utilities and anyone still on Oracle: inventory a production clone before a migration number reaches a budget deck. The residue list is what the estimate rests on.
- Healthcare and insurance: a dated, logged restore drill is the cheapest compliance evidence you will produce this quarter.
- SaaS and trading systems: forty indexes accumulated over five years of features cost write throughput on every insert. Rank by bloat and zero-scan history, not by vibes.
- Logistics and high-churn tables: autovacuum falling behind is a latency bug that looks like a query bug. Watch it before it becomes the incident.
Do this week
Run pgrecon against a clone of your oldest Oracle schema and read the residue file. Schedule one restore drill and attach its output to a ticket. Then count the indexes nothing has scanned in a month:
SELECT relname, indexrelname, idx_scan,
pg_size_pretty(pg_relation_size(indexrelid)) AS size
FROM pg_stat_user_indexes
WHERE idx_scan = 0
AND indexrelid NOT IN (SELECT conindid FROM pg_constraint)
ORDER BY pg_relation_size(indexrelid) DESC;
If that returns rows measured in gigabytes, you have found next month’s write-path win without buying anything.
If you are scoping an Oracle-to-Postgres move and want the assessment done properly before you commit, our Postgres migration assessment for Houston teams starts with exactly that inventory — read-only, offline, and argued line by line.
