PostgreSQL  

Preparing PostgreSQL 14 Upgrades Before November

PostgreSQL upgrades are usually postponed because the application is working, the database is stable, and nobody wants to introduce unnecessary risk.

That approach can become a problem when a PostgreSQL major version reaches the end of its supported life. PostgreSQL 14 is approaching that point, so teams still running PostgreSQL 14 should treat the upgrade as planned engineering work rather than waiting until the deadline is close.

For .NET applications, a PostgreSQL upgrade involves more than installing a newer database server. The application may depend on Npgsql, Entity Framework Core, database extensions, SQL behavior, indexes, stored procedures, connection settings, and deployment infrastructure.

This article walks through a practical approach for preparing a PostgreSQL 14 application for a major-version upgrade.

Why PostgreSQL 14 Upgrades Need Planning

A major PostgreSQL upgrade is different from a routine minor-version update.

Major releases can introduce changes in:

  • SQL behavior

  • Query planning

  • Performance characteristics

  • System catalogs

  • Extensions

  • Configuration

  • Driver compatibility

  • Database tooling

  • Replication and backup workflows

PostgreSQL 14 is scheduled to stop receiving fixes on November 12, 2026.

That date should be treated as a planning milestone. The goal is not to perform an emergency migration immediately before support ends. The goal is to have enough time to test, fix compatibility problems, rehearse the migration, and schedule production downtime if required.

Start With an Upgrade Inventory

Before choosing a target PostgreSQL version, understand what your current environment actually contains.

Create an inventory covering:

AreaWhat to Check
PostgreSQLExact 14.x version
Database sizeTotal and largest databases
TablesLargest and busiest tables
ExtensionsInstalled extensions and versions
Application.NET and ORM versions
DriverNpgsql version
SQLCustom queries and database functions
InfrastructureContainers, VMs, managed database services
BackupsBackup and restore process
ReplicationStreaming/logical replication if used
MonitoringDatabase and application monitoring

You can begin with:

SELECT version();

Then inspect installed extensions:

SELECT
    extname,
    extversion
FROM pg_extension
ORDER BY extname;

This inventory often reveals dependencies that are easy to miss.

Choose the Target PostgreSQL Version

Do not approach the upgrade as simply:

PostgreSQL 14 → PostgreSQL 15

First determine which supported PostgreSQL release is the appropriate target for your organization.

Consider:

  • Application compatibility

  • Npgsql support

  • ORM compatibility

  • Extension availability

  • Hosting-provider support

  • Operational tooling

  • Internal upgrade policies

  • Expected support lifetime

Choosing a newer supported release can reduce the number of future major-version upgrades you need to perform, but the decision should be based on your application's compatibility and operational requirements.

Check the .NET Application Stack

The database server is only one part of the system.

A typical .NET application might look like this:

ASP.NET Core
      |
      v
Entity Framework Core
      |
      v
Npgsql
      |
      v
PostgreSQL 14

After the upgrade:

ASP.NET Core
      |
      v
Entity Framework Core
      |
      v
Npgsql
      |
      v
Target PostgreSQL Version

Before migrating, verify that the versions of .NET, EF Core, and Npgsql used by the application support your target PostgreSQL release.

For example, inspect the project file:

<ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore"
                      Version="..." />

    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL"
                      Version="..." />
</ItemGroup>

Do not upgrade every dependency at the same time without a reason. Separating database-version changes from unrelated application changes makes failures much easier to diagnose.

Capture Your Important Queries

Application compatibility testing should focus on real workload patterns.

For an EF Core application, identify important LINQ queries:

var orders = await dbContext.Orders
    .Where(o => o.CustomerId == customerId)
    .OrderByDescending(o => o.CreatedAt)
    .Take(50)
    .ToListAsync();

Also capture the generated SQL where practical.

Test queries involving:

  • Joins

  • Aggregations

  • Pagination

  • Sorting

  • JSON

  • Arrays

  • Full-text search

  • Transactions

  • Bulk operations

  • Database functions

A query that works syntactically on both versions can still have a different execution plan.

Test Against Production-Like Data

One of the most common upgrade-testing mistakes is using a small development database.

Suppose production has:

orders:       150 million rows
customers:     8 million rows

while the test environment contains:

orders:       50,000 rows
customers:    5,000 rows

A query that looks fast in development may behave differently at production scale.

You do not necessarily need a complete production copy. You need a dataset that reproduces important characteristics such as:

  • Table sizes

  • Data distribution

  • Frequently accessed records

  • Large and small tenants

  • NULL frequency

  • Index distribution

  • Typical date ranges

Sensitive production data should also be handled according to your organization's security and privacy requirements.

Compare Query Execution Plans

Before the migration, collect execution plans for important queries.

For example:

EXPLAIN (ANALYZE, BUFFERS)
SELECT
    o.id,
    o.total_amount,
    o.created_at
FROM orders o
WHERE o.customer_id = 1001
ORDER BY o.created_at DESC
LIMIT 50;

Run equivalent tests against the current PostgreSQL environment and the target version.

Look for:

  • Sequential scans where an index was previously used

  • Different join algorithms

  • Increased row estimates

  • Higher execution time

  • Increased buffer reads

  • Additional sorting

  • Changes in aggregation strategy

Do not assume that a different plan automatically means a regression. Query planners can legitimately select different strategies.

The important thing is to measure the resulting behavior.

Test Database Extensions

Extensions deserve special attention during major-version upgrades.

List the extensions currently installed:

SELECT
    extname,
    extversion
FROM pg_extension;

For every extension, determine:

  1. Is it supported on the target PostgreSQL version?

  2. Is a compatible version available?

  3. Does the upgrade process require additional steps?

  4. Does the application depend directly on the extension?

This is particularly important for applications using specialized indexing, search, geospatial functionality, or other PostgreSQL extensions.

Do not assume that because PostgreSQL itself supports the target version, every extension in your environment automatically does.

Test Migrations and Database Objects

Applications often contain more database logic than developers realize.

Review:

  • Tables

  • Indexes

  • Views

  • Materialized views

  • Functions

  • Triggers

  • Sequences

  • Generated columns

  • Constraints

  • Custom types

  • Extensions

For EF Core applications, verify that migrations still work against the target database.

For example:

dotnet ef database update

Run migrations against a disposable target-version database before attempting production deployment.

This gives you an opportunity to identify database-object compatibility problems without risking production data.

Validate Backup and Restore

A migration plan is incomplete without a recovery plan.

Before upgrading, verify that your backups can actually be restored.

A backup that successfully completes but cannot be restored is not a reliable recovery strategy.

Your test should cover:

Production Backup
       |
       v
Backup Storage
       |
       v
Restore
       |
       v
Target PostgreSQL Environment
       |
       v
Application Validation

Measure the restore process and record the time required.

This gives the team a realistic understanding of recovery capability.

Choose an Upgrade Strategy

There are several approaches to a major PostgreSQL upgrade.

ApproachAdvantagesConsiderations
In-place upgradeCan be straightforwardRequires careful downtime planning
Logical migrationCan provide more migration flexibilityMore operational complexity
Dump and restoreFamiliar and portableCan be slow for large databases
Managed-service upgradeProvider may automate partsProvider-specific limitations
Blue/green approachStrong rollback potentialRequires additional infrastructure

The right choice depends on database size, downtime requirements, infrastructure, replication architecture, and operational capabilities.

There is no single migration method that is best for every PostgreSQL installation.

Build an Upgrade Test Environment

A strong upgrade process should have at least one environment that resembles production.

A useful structure is:

PostgreSQL 14
     |
     | Baseline
     v
Production-Like Test Data
     |
     v
Target PostgreSQL
     |
     | Compatibility Testing
     v
.NET Application

Run the same application test suite against both versions.

Include:

  • Authentication

  • CRUD operations

  • Search

  • Reporting

  • Background jobs

  • Transactions

  • Scheduled tasks

  • APIs

  • Batch processing

The database upgrade should be tested as an application change, not just an infrastructure change.

Run Application-Level Regression Tests

Automated integration tests are especially valuable.

For example:

[Fact]
public async Task Should_Create_Order()
{
    await using var context = CreateDbContext();

    var order = new Order
    {
        CustomerId = 1001,
        Status = "Pending",
        TotalAmount = 149.99m
    };

    context.Orders.Add(order);

    await context.SaveChangesAsync();

    var savedOrder = await context.Orders
        .FirstAsync(x => x.Id == order.Id);

    Assert.Equal(149.99m, savedOrder.TotalAmount);
}

The same test suite should run against the existing PostgreSQL version and the target version.

This catches problems that database-only testing cannot detect.

Test Connection Pooling and Transactions

Production applications normally use connection pooling.

A basic .NET connection string might look like:

Host=localhost;
Port=5432;
Database=appdb;
Username=appuser;
Password=secret;
Pooling=true;
Maximum Pool Size=100;

The actual values should match your application's requirements.

Test:

  • Connection acquisition

  • Connection release

  • Pool exhaustion

  • Transaction rollback

  • Long-running transactions

  • Concurrent requests

Also check that failed database operations do not leave application connections or transactions in an unexpected state.

Common Upgrade Mistakes

Waiting Until the Support Deadline

The November deadline should be treated as a reason to start planning early, not as the migration date.

Testing Only Schema Compatibility

A database can accept the schema while application queries still experience regressions.

Ignoring Extensions

Extensions can introduce independent compatibility requirements.

Changing Too Many Variables

Avoid combining the PostgreSQL upgrade with large application refactoring, ORM migration, infrastructure redesign, and unrelated dependency upgrades.

Keeping the change set controlled makes troubleshooting significantly easier.

Skipping Restore Testing

A migration without a tested recovery path creates unnecessary operational risk.

Troubleshooting Upgrade Problems

A Query Became Slower

Start with:

EXPLAIN (ANALYZE, BUFFERS)
SELECT ...;

Compare execution plans and check statistics, indexes, data distribution, and configuration.

EF Core Queries Fail

Capture the generated SQL and run it directly against the target PostgreSQL version.

This helps determine whether the issue originates from PostgreSQL, EF Core, or the database driver.

An Extension Cannot Be Installed

Check whether a compatible extension version exists for the target PostgreSQL release and whether your hosting environment supports it.

The Application Cannot Connect

Check:

  • Host and port

  • Credentials

  • SSL settings

  • Firewall rules

  • Connection-string changes

  • Npgsql compatibility

  • PostgreSQL authentication configuration

Best Practices

  1. Start with an inventory. Know exactly what PostgreSQL 14 supports in your environment.

  2. Choose the target deliberately. Consider support lifetime and application compatibility.

  3. Test the complete .NET stack. PostgreSQL, Npgsql, EF Core, and the application should be tested together.

  4. Use production-like data. Query behavior depends heavily on data volume and distribution.

  5. Compare execution plans. Investigate meaningful changes rather than assuming they are regressions.

  6. Test extensions separately. Extension compatibility can become a migration blocker.

  7. Validate backups and restores. Recovery should be demonstrated, not assumed.

  8. Rehearse the migration. A dry run exposes operational problems before production.

  9. Keep the change set controlled. Avoid unrelated application changes during the database upgrade.

  10. Define rollback criteria. Decide in advance what conditions require stopping or reversing the migration.

Frequently Asked Questions

When should a PostgreSQL 14 upgrade be completed?

PostgreSQL 14 is scheduled to reach end of support on November 12, 2026. Teams should plan the migration early enough to complete compatibility testing and address unexpected issues before that date.

Do I need to upgrade Npgsql?

You should verify that your Npgsql version supports the target PostgreSQL release and your application stack. Do not upgrade it blindly; validate the dependency combination through testing.

Should I test with the complete production database?

Not necessarily. A production-like dataset can be sufficient if it reproduces the characteristics that influence your application's behavior. Follow your organization's data-security requirements when creating test datasets.

Is a PostgreSQL major upgrade always associated with application changes?

No. Many applications can continue working with minimal or no code changes, but that should be demonstrated through testing rather than assumed.

What is the most important upgrade test?

There is no single test. A reliable upgrade assessment combines functional testing, query-plan comparison, performance testing, extension validation, backup/restore testing, and application-level regression testing.

Conclusion

The PostgreSQL 14 support deadline should be treated as an engineering planning milestone, not a last-minute migration deadline. A successful upgrade depends on understanding the entire dependency chain from the PostgreSQL server through Npgsql and the .NET application.

Start by inventorying the current environment, selecting an appropriate target version, and building a production-like test environment. Then test real application queries, database objects, extensions, transactions, connection pooling, backups, and recovery procedures.

The most valuable upgrade preparation is a rehearsed process with measurable results. When the production migration finally happens, the team should already know how the application behaves on the target PostgreSQL version, how long the migration takes, what can go wrong, and what the recovery path looks like.