How do I know if my PostgreSQL version has reached end of life?
Run SHOW server_version_num; and read the first two digits as the major. The PostgreSQL project supports each major for five years from its first release. As of 2026-09-17, majors 18, 17, 16, 15 and 14 are supported; 13 and everything older are end of life and will never get another fix.
Key facts
| Fact | Value | |---|---| | Support window per major | 5 years from initial release, then a final minor and EOL (postgresql.org/support/versioning) | | Minor release cadence | At least once every three months (postgresql.org/support/versioning) | | Supported majors on 2026-09-17 | 18 (EOL 2030-11-14), 17 (2029-11-08), 16 (2028-11-09), 15 (2027-11-11), 14 (2026-11-12) (endoflife.date/postgresql) | | Already out of support | 13 (EOL 2025-11-13), 12 (2024-11-21), 11 (2023-11-09), 10 (2022-11-10) and older (postgresql.org/support/versioning) | | Nearest cliff | PostgreSQL 14 stops receiving fixes on 2026-11-12 — under two months away | | Current minors (2026-08 releases) | 18.6, 17.11, 16.15, 15.19, 14.24 (endoflife.date/postgresql) | | Minor upgrade | Binary swap plus restart; no dump, no restore, no pg_upgrade |
Why this happens
PostgreSQL's versioning policy is short and absolute: "The PostgreSQL Global Development Group supports a major version for 5 years after its initial release. After this, a final minor version will be released and the software will then be unsupported (end-of-life)." There is no extended-support tier from the community, no paid exception, and no negotiation. A major released in September of year N gets its last minor in November of year N+5.
Within that window, each major gets a minor release at least once a quarter, carrying bug fixes and, when needed, security fixes. Minor releases never change the on-disk format, so upgrading within a major is a binary swap and a restart. That is the whole reason the project can say, without much hedging, that you should always run the current minor for your major.
The date that catches teams out is the one nobody schedules around. Major 13 reached its final minor on 2025-11-13. Nothing broke on the 14th. The instance kept serving queries exactly as before, which is precisely the problem: an EOL PostgreSQL gives you no signal at all. It simply stops receiving fixes, and you find out months later when a CVE lands with no patch for your branch.
What that actually costs:
- No security fixes. A vulnerability disclosed after your branch's final minor is fixed in 14 through 18 and not in yours. Your only remedy is a major upgrade, executed under time pressure.
- No data-corruption fixes. The ones that matter tend to be subtle — index corruption after a collation change, a planner bug that returns wrong rows, a replication edge case. These are found and fixed continuously in supported branches.
- Provider-scheduled upgrades. RDS, Cloud SQL and Azure publish their own end-of-support dates and will force a major upgrade on their calendar if you have not done one on yours. That upgrade happens in a maintenance window you did not choose.
- Extensions dropping support. PostGIS, TimescaleDB, pgvector and the rest build against supported majors. Once yours is EOL, the next extension release you want may simply not have a package for it.
How to detect it
Three ways to ask, and they are not interchangeable:
SELECT version();
-- PostgreSQL 18.1 on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
SHOW server_version;
-- 18.1
SHOW server_version_num;
-- 180001
version() is a human-readable string that includes the compiler and platform; it is useful in a ticket and awkward everywhere else. server_version is the dotted form. server_version_num is the one your scripts should compare, because it is an integer: major × 10000 + minor. So 18.1 is 180001, 17.11 is 170011, 13.23 is 130023. Integer comparison gets the ordering right every time, whereas string comparison on server_version will happily tell you that "9.6" sorts after "18.1".
A gate you can drop into a check script:
SELECT current_setting('server_version_num')::int AS version_num,
current_setting('server_version_num')::int / 10000 AS major,
current_setting('server_version_num')::int / 10000 >= 14 AS is_supported_today;
From the shell, the same numbers without a psql session:
psql -Atc "SHOW server_version_num"
pg_config --version # the version of the binaries on this host, not the running server
Those two can disagree. If you have installed new packages but not restarted, pg_config reports the new binaries while the running server still reports the old ones — which is exactly the state a half-finished minor upgrade leaves you in.
Then compare the major against the table above, and the minor against the current minor for your branch. Being four minors behind on a supported major is a different, smaller problem than being on an EOL major — but it is still a problem, because those four minors contain fixes someone thought were worth shipping.
How MyDBA shows this

The estate view lists every monitored instance with the version the collector read from that server, and the "Versions & EOL" panel (frontend/src/components/overview/panels/VersionsPanel.tsx) flags any database on a major that is already past its EOL date or inside a year of it — "EOL" in red, "near EOL" in amber, each with the date. It is derived from the collector-reported version string, so it reflects what is actually running, not what a runbook says should be running. The per-connection health check page shows the configuration domain alongside it, which is where the upgrade-adjacent findings live: across 50 monitored instances, 16% fail the pg_stat_statements check and, across 38 evaluated for it, 52.6% fail log_lock_waits — both settings and extensions that a major upgrade can silently reset if you do not carry your configuration forward.

If you want the version inventory for your own fleet without setting anything up, the free PostgreSQL health check will read it and score the configuration domain with it.
How to fix it
If you are behind on minors within a supported major, do that first — it is the cheap one. Stop the server, install the new packages for the same major, start it. No dump, no restore, no pg_upgrade, no catalog change. Read the release notes for your branch anyway: a handful of minors have shipped with a note saying you should reindex particular indexes afterwards.
If your major is EOL, you need a major upgrade, and there are three paths:
1. pg_dumpall and restore. Simple, verifiable, and slow — downtime scales with data size, so it is fine at tens of gigabytes and painful past that. It is also the only path that rebuilds every index from scratch, which sidesteps collation problems entirely. 2. pg_upgrade --link. Hard-links the data files into the new cluster instead of copying them, so the downtime is minutes rather than hours regardless of size. The catch: --link means the old cluster is no longer safely startable once the new one has run, so your rollback plan is your backup, not the old data directory. Always run pg_upgrade --check first, and take a fresh backup before the real run. 3. Logical replication. Build the new major alongside the old, replicate into it, and cut over when the lag is near zero. This is the near-zero-downtime path and the most work: it needs primary keys (or replica identities) on replicated tables, and sequences, large objects and DDL do not come across on their own. We walk through the whole cutover in zero-downtime PostgreSQL major upgrades.
Pick on data size and downtime budget, in that order. Under ~50 GB with a maintenance window, dump/restore is the least that can go wrong. Large and with a window, pg_upgrade --link. Large and without a window, logical replication.
How to prevent it
Before any major upgrade, work through this:
- Extension compatibility. List what you have (
SELECT name, default_version, installed_version FROM pg_available_extensions WHERE installed_version IS NOT NULL;) and confirm each one has a build for the target major before you start. PostGIS and TimescaleDB have their own version matrices, and TimescaleDB in particular wants to be upgraded on the old major first. Which PostgreSQL extensions are worth installing covers the ones most estates actually run. pg_upgrade --check. Run it against the real cluster, not a scrubbed copy. It catches incompatible data types, missing extension libraries and unknown tablespaces in seconds, before you have committed to anything.- Collation and glibc. This is the one that bites quietly. If the new host has a different glibc — a new OS release, a new base image — string sort order can change, and every index on a text column built under the old collation is now potentially wrong: unique constraints that no longer catch duplicates, range scans that miss rows. Compare
datcollversioninpg_databasebefore and after, and if it moved,REINDEXevery text index (or use the dump/restore path, which rebuilds them anyway).pg_upgradedoes not do this for you. - Replicas. Physical replicas cannot be upgraded by replicating the upgrade; the standard approach is to upgrade the primary and rebuild the standbys from it. Plan for that window, and check your
max_wal_sizeand archive settings survive the rebuild. - Configuration carry-over.
postgresql.confandpg_hba.confare not migrated bypg_upgrade. Diff them deliberately rather than copying the old file wholesale — some defaults change between majors for good reasons.
Then make the next one routine: put the EOL date of your current major in the calendar with a year's notice, alert on being more than two minors behind, and re-check at every OS upgrade. New majors arrive every September, which means a rough plan of "upgrade a major every two to three years" keeps you permanently inside the window. What is new in each one is catalogued in PostgreSQL features by version, and version currency belongs on the same list as the rest of your PostgreSQL security checklist.
FAQ
Is PostgreSQL 13 still supported?
No. PostgreSQL 13 received its final minor, 13.23, on 2025-11-13 and is end of life. Any vulnerability or data-corruption bug found after that date is fixed in 14 through 18 only. 12, 11, 10 and everything older passed EOL earlier still.
Do I have to do a major upgrade to apply a security fix?
Only if your major is EOL. On a supported major, security fixes arrive as minor releases: swap the binaries, restart, done — no dump, no restore, no catalog rewrite. On an EOL major there is no minor to apply, so the fix is a major upgrade whether you planned one or not.
Can I skip majors, for example 12 straight to 18?
Yes. pg_upgrade, dump/restore and logical replication all support jumping several majors at once, and jumping is usually less work than a chain of upgrades. The risk is that behaviour changes from every intervening release land together, so read the incompatibilities section of each major's release notes, not just the target's.
What is the difference between server_version and server_version_num?
server_version is the dotted string, like 18.1. server_version_num is the same value as an integer — major × 10000 + minor, so 180001. Scripts should compare the numeric form: string comparison sorts 9.6 after 18.1, which is how version gates end up silently inverted.
How long do I have on PostgreSQL 14?
Until 2026-11-12, its final minor release. If you are on 14 as of this writing, you have under two months of fixes left and should be scheduling the upgrade now rather than planning to schedule it.
Part of the The PostgreSQL health check checklist guide. Last verified against PostgreSQL 18, 2026-09-17.