Skip to content

Rate this page
Thanks for your feedback
Thank you! The feedback has been submitted.

Get free database assistance or contact our experts for personalized support.

Pre-migration compatibility checks

Important

Read this before you migrate.

Complete these checks before you pick a migration method. Verify that source and target environments are compatible. Migration methods such as pgBackRest restore, standby replication or reusing the existing PostgreSQL data volume all reuse the source PGDATA files. For all these methods, CPU architecture and the PostgreSQL major version must match. If they don’t, migrate using pg_dump / pg_restore instead.

Differences in the operating system, libraries like glibc, ICU, or PostgreSQL extensions do not always block reuse of PGDATA. But you must take extra steps before or after the migration.

Decide whether you can reuse the data files

Use this flow to interpret the checks. Then gather the facts in the sections that follow.

flowchart TD
    A[Compare PostgreSQL major versions] -->|Different| B[Do not use standby, backup/restore, or volume reuse]
    A -->|Same| C[Compare CPU architecture]
    C -->|Different| D[Prefer logical migration]
    C -->|Same| E[Compare OS / glibc / ICU]
    E -->|Same| F[Compare extensions]
    E -->|Different| G[Check collation versions]
    G -->|Match| F
    G -->|Mismatch| H[Identify affected indexes]
    H --> I[REINDEX]
    I --> J[REFRESH COLLATION VERSION]
    J --> F
    F --> K[Trial runs]
    K --> L[Fix issues if any]
    L --> M[Migrate]
    M --> N[Validate PostgreSQL and check the logs]

Compare PostgreSQL major versions

The PostgreSQL major version of the source and target database images must match.

Check the source (Crunchy) PostgreSQL version:

kubectl exec -n <namespace> <source-postgres-pod> -c database -- \
  postgres --version
Sample output
postgres (PostgreSQL) 18.6

Check the version in the target Percona image as well. Find tags in Percona certified images. If the Percona cluster is not running yet, start a temporary Pod from the target image:

kubectl run pg-image-check --rm -it --restart=Never \
  --image=<percona-postgres-image> -- \
  postgres --version

The major versions must match, for example:

Source: postgres (PostgreSQL) 18.6
Target: postgres (PostgreSQL) 18.6 - Percona Server for PostgreSQL 18.6.1

A difference in the minor version is normally supported by PostgreSQL’s physical storage format, but the target minor version should be equal to or newer than the source.

Do not reuse PGDATA or restore a physical backup directly into a different PostgreSQL major version.

Compare CPU architecture

Check the architecture of both the source and target PostgreSQL containers:

kubectl exec -n <namespace> <source-postgres-pod> -c database -- uname -m
kubectl exec -n <namespace> <percona-postgres-pod> -c database -- uname -m
Expected output
x86_64

or:

aarch64

The source and target must use the same architecture.

For example:

x86_64 -> x86_64    OK
ARM64  -> ARM64     OK
x86_64 -> ARM64     Not OK

Use pg_dump / pg_restore when you migrate across incompatible architectures.

Compare OS, glibc, and ICU

Run these commands against the source Crunchy pod. Repeat them against the target Percona image (use a temporary Pod if the cluster is not running yet).

Check operating system

Check the operating system used by the PostgreSQL container:

kubectl exec -n <namespace> <postgres-pod> -c database -- \
  cat /etc/os-release

Check the glibc version:

kubectl exec -n <namespace> <postgres-pod> -c database -- \
  getconf GNU_LIBC_VERSION

Example:

glibc 2.34

Percona PostgreSQL images are based on Red Hat Universal Base Image (UBI) . Each UBI major ships a different glibc version:

UBI version glibc version
UBI 8 glibc 2.28
UBI 9 glibc 2.34
UBI 10 glibc 2.39

Use the same UBI major for every instance in a cluster. Find image tags in Percona certified images.

If the Crunchy image is UBI 8 and you use the default Percona image (UBI 9), you will see a glibc change:

Source:
  UBI 8
  glibc 2.28

Target:
  UBI 9
  glibc 2.34

A different glibc version does not by itself make the PostgreSQL data directory incompatible. glibc provides locale and collation rules that PostgreSQL uses. A change in these rules can make existing collation-dependent indexes inconsistent with the target operating system. See Locale data changes in the PostgreSQL wiki.

Check ICU library version

PostgreSQL may also use ICU for collations. Check the locale provider in each database:

  SELECT datname, datlocprovider, datcollversion FROM pg_database;
Sample output
  datname  | datlocprovider | datcollversion
-----------+----------------+----------------
postgres  | c              | 2.34
template1 | c              | 2.34
template0 | c              |
cluster1  | c              | 2.34
(4 rows)

c is libc (glibc). i is ICU. If the provider is i and the source and target images ship different ICU libraries, treat that the same as a glibc change.

If glibc or ICU differs, run the collation checks after PostgreSQL starts on the target image. You can run the index scan on the source cluster beforehand to estimate the work.

Connect to PostgreSQL with the privileges of the superuser or the database owner and run the following query:

SELECT DISTINCT
    indrelid::regclass::text,
    indexrelid::regclass::text,
    collname,
    pg_get_indexdef(indexrelid)
FROM (
    SELECT
        indexrelid,
        indrelid,
        indcollation[i] coll
    FROM
        pg_index,
        generate_subscripts(indcollation, 1) g(i)
) s
JOIN pg_collation c ON coll = c.oid
WHERE
    collprovider IN ('d', 'c')
    AND collname NOT IN ('C', 'POSIX');

Check indexes that rely on collations other than C or POSIX and whose collations were provided by the operating system (c) or dynamic libraries (d). If you see affected indexes, find the databases whose collation version changed:

SELECT datname, datlocprovider, datcollate, datcollversion
FROM pg_database;
Sample output
datname   | datlocprovider | datcollate  | datcollversion
----------+----------------+-------------+----------------
postgres  | c              | en_US.utf-8 | 2.28
template1 | c              | en_US.utf-8 | 2.28
template0 | c              | en_US.utf-8 |
cluster1  | c              | en_US.utf-8 | 2.28

Compare extensions

Record the extension list and versions on the source cluster before you migrate.

Extensions are installed per database. Check every application database, not only postgres:

SELECT
    extname,
    extversion
FROM pg_extension
ORDER BY extname;
Sample output
extname             | extversion
--------------------+-----------
plpgsql             | 1.0
pg_stat_statements  | 1.12
postgis             | 3.4.2
pgcrypto            | 1.3

Verify that each extension is available in the target Percona image. Percona Distribution for PostgreSQL ships a defined set of tested extensions. Their versions may differ from the Crunchy image.

You can also add custom extensions if you need them. Evaluate the risk before you add any extension.

Pay particular attention to extensions that contain native C/C++ libraries. Those extensions need a shared library in the PostgreSQL installation, not only a catalog entry in PGDATA. Do not assume an extension is available because it exists in pg_extension.

Before you cut over

Perform at least three successful trial runs in a comparable test environment and validate the application after each one. The first run usually exposes missing steps, the second confirms the fixes, and the third shows that the procedure is repeatable and the cutover time is predictable. Capture that as a detailed, environment-specific runbook before you migrate production workloads.

After PostgreSQL starts under Percona Operator for PostgreSQL, check the PostgreSQL logs for errors, then confirm that collation rebuilds and extensions are complete.


Last update: September 8, 2026
Created: September 8, 2026