6 min read
Use PostgreSQL 19 RC 1 to rehearse compatibility
Test the system around PostgreSQL
A benchmark can tell me whether a workload performs differently; it cannot tell me whether the application still migrates cleanly, whether its driver behaves as expected, or whether my restore procedure works. I would use PostgreSQL 19 RC 1 to rehearse those integrations, not to make a production adoption decision.
The PostgreSQL project announced RC 1 on October 15, 2026, and describes release candidates as pre-release versions for testing, not production use. Its beta testing guidance specifically calls out testing by developers of platforms, drivers, tools, and utilities that depend on PostgreSQL. That is the useful frame for an application team too: treat the candidate as a chance to find compatibility work while there is still room to address it.
I would not start by asking whether PostgreSQL 19 is faster for a representative query. I would start with the ways my application depends on PostgreSQL: schema and data migrations, driver behavior, extensions, database initialization, backups, restores, and the operational steps around a major-version upgrade. A performance test can be one part of qualification, but it is a narrow answer to a different question.
Make the test resemble the real upgrade
A useful rehearsal needs more than a fresh database and a successful connection. I would bring up an isolated RC 1 environment using the same kind of installation and configuration I expect to operate, then run the application’s existing migration path against it. The goal is not to invent a new test suite for the candidate. It is to exercise the existing one against a different server version.
I would record the environment and commands so that a failure can be reproduced, and I would keep the current-version run as a comparison. For example, a pipeline could make the server version an explicit input to a migration-and-integration job:
name: PostgreSQL compatibility
on:
workflow_dispatch:
jobs:
integration:
runs-on: ubuntu-latest
strategy:
matrix:
postgres: ["18", "19-rc1"]
steps:
- uses: actions/checkout@v4
- name: Start PostgreSQL
run: ./scripts/start-postgres.sh "${{ matrix.postgres }}"
- name: Apply migrations
run: ./scripts/migrate-test-database.sh
- name: Run integration tests
run: ./scripts/test-database-integration.sh
The image tags and startup commands need to match the way a team actually provisions PostgreSQL; the point of the example is to make the tested version visible in the job, not to prescribe a particular container image. I would also make sure the test checks the application’s important database paths, rather than stopping at a successful health check. A server that starts is not evidence that the application’s schema, queries, or migration sequence work.
Migrations deserve their own attention. I would test both applying the full migration history to a clean database and upgrading a representative copy of the current schema and data through the normal migration process. Those cover different starting conditions. I would inspect the resulting schema and exercise the application flows that depend on the changed tables, constraints, indexes, or stored logic. If a migration has special operational steps, I would run those too, rather than assuming that a green test of the migration tool covers the whole procedure.
Include dependencies and operational procedures
The application does not integrate with the PostgreSQL server alone. I would list the database drivers, extensions, migration tools, and any other PostgreSQL-dependent components in the system, then verify their actual versions and installation paths in the test environment. For each dependency, I would ask a practical question: can I install or load it, can the application use the functions or types it relies on, and does the test environment behave as expected when it is present?
That is more useful than treating a successful connection as a compatibility verdict. A driver may connect while a less frequently used query path still needs testing. An extension may be installed in one environment but missing from the process that builds the test database. A migration can apply while a subsequent operation assumes an object or behavior that the migration did not produce. These are test-design risks, not claims that PostgreSQL 19 RC 1 has a particular defect. The point is to make the dependencies visible and check the paths the application actually uses.
I would include the operational runbook in the rehearsal. The PostgreSQL 19 RC 1 announcement says upgrading from earlier versions requires a major-version upgrade strategy, such as pg_upgrade or pg_dump and pg_restore. I would test the strategy I expect to use, not just read about an alternative. That means rehearsing the surrounding steps as well: how I prepare the source, where I take and verify backups, how I provision the target, and how I establish that the application can use the upgraded database.
A runbook test should produce evidence that another person can follow. I would record the starting version, the chosen upgrade method, the commands and configuration used, any required extension setup, the checks performed after the upgrade, and the conditions under which I would stop or roll back. If a step depends on a manual judgment, I would make that explicit. Hidden assumptions are exactly what a rehearsal should uncover.
Keep qualification separate from adoption
An RC is a useful test target precisely because it is not a production commitment. The PostgreSQL project says release candidates are made available so people can test before the initial release, and notes that changes can still be made before general availability in its beta testing guidance. I would keep the test environment isolated, avoid directing production traffic to it, and treat results as evidence about readiness—not as permission to upgrade.
I would also keep a short findings list with three categories: confirmed compatible, needs investigation, and blocked. A failed test should say what failed and how to reproduce it; a passing test should say what path it covered. “The suite passed” is not enough if the suite never exercises an extension or the upgrade route we plan to use. Equally, a gap in test coverage is not proof of incompatibility. It is a reason to decide whether to add a check or accept an explicit uncertainty.
If the rehearsal finds work, I would fix or document that work while the upgrade is still a qualification exercise. If it finds none, I would have stronger evidence for the eventual adoption decision, but not a substitute for that decision. I want an RC run to tell me where the integration surface needs attention before production planning begins; a benchmark alone cannot do that.
Drafted with AI assistance, reviewed and edited by Ali.