Migrating the Database

Migrating Your Database to PostgreSQL

Liferay DXP 2026.Q3+

Migrating a Liferay DXP database to PostgreSQL has two phases. First, export the database schema to SQL files from either Server Administration or the REST API. Then run the database migration importer tool (db_migration_importer.sh) to copy the schema and its data into an empty PostgreSQL database. Supported source databases are DB2, MariaDB, MySQL, Oracle, and SQL Server. PostgreSQL is the only supported target. Liferay DXP must be shut down for the import. Downtime starts with that shutdown and ends after you restart on PostgreSQL.

For releases before 2026.Q3, see the PostgreSQL migration Knowledge Base article.

Warning

Back up your database before migrating.

Exporting the Database Schema

Exporting the schema requires a system administrator (omniadmin) account and a Liferay DXP instance running on the source database.

  1. Go to Control PanelSystemServer Administration.

  2. Click the Database Migration tab.

  3. Complete these fields:

    Export Files Path: Enter the path of a writable directory on the server. Liferay DXP writes the SQL files and report there. This field is required.

    Text Verification: Complete the CAPTCHA challenge. By default, this field is hidden after your first successful challenge in a session.

    The Database Migration tab has an Export Files Path field, a CAPTCHA image with a Text Verification field, and an Export button.

  4. Click Export.

The result appears in a message at the top of the tab:

ConditionMessage
The export succeedsThe database schema was exported successfully to [path].
The export path is not writableUnable to export the database schema. Verify the export path is writable.
The text verification entry is wrongText verification failed.
The CAPTCHA engine is misconfiguredA CAPTCHA error occurred. Please contact an administrator.

The export writes to the Liferay DXP server’s file system rather than to your workstation. Confirm that tables.sql, indexes.sql, and db_migration_schema_export_report.txt exist in the directory named in the success message. A directory that doesn’t exist yet is created rather than rejected, so a mistyped path succeeds into a new directory.

Exporting the Schema with the REST API

To export the schema from a script instead of the UI, call POST /o/admin-server/v1.0/database-schema-export with the export path in the request body. exportFilesPath is a directory on the Liferay DXP server. The caller must be a system administrator. Unlike the UI, the REST API has no text verification challenge. Replace test@liferay.com:test with your own administrative credentials. Never use default credentials in production.

curl -X POST 'http://localhost:8080/o/admin-server/v1.0/database-schema-export' \
  -H 'Content-Type: application/json' \
  -u 'test@liferay.com:test' \
  -d '{
        "exportFilesPath": "/directory/"
      }'

A successful call returns 200 with the export path, the names of the files written, and the name of the report file:

{
   "exportFilesPath": "/directory",
   "fileNames": [
      "indexes.sql",
      "tables.sql"
   ],
   "reportFileName": "db_migration_schema_export_report.txt"
}

exportFilesPath in the response shows where the files were written, which may not match the path you sent.

Status CodeCause
400Blank exportFilesPath value or a path the server cannot write to
403Caller without system administrator permissions

To browse the full OpenAPI specification and run requests interactively, open the API Explorer at http://[host]:[port]/o/api.

Reviewing the Exported Files

The export writes table definitions to tables.sql, index definitions to indexes.sql, and a report to db_migration_schema_export_report.txt. These files contain schema definitions only. The importer reads table data from the source database when it runs, so writes made between the export and the shutdown are included.

When database partitioning is enabled, the default instance keeps the plain tables.sql and indexes.sql names, and every non-default instance gets its own pair of files prefixed with its company ID: [companyId]_tables.sql and [companyId]_indexes.sql.

db_migration_schema_export_report.txt lists the tables the export did not write to tables.sql. These tables and their data are absent from PostgreSQL after the migration. To keep a table instead, copy the original files first, then add its definition to tables.sql and its indexes to indexes.sql, matching the columns of the source table.

Warning

Hand-editing the exported SQL files risks a failed or incomplete import. The files use PostgreSQL syntax, not your source database’s.

Importing into PostgreSQL

The importer tool requires a Java runtime on its path and Linux or macOS. Liferay DXP includes it at [Liferay Home]/tools/portal-tools-db-migration-importer (see Liferay Home). Run it from a host that can reach both the source database and the target PostgreSQL database. The --source-user account must have read access to every partition in the source database.

  1. Create an empty PostgreSQL database. The target user must be able to create schemas and tables.

  2. For a DB2, Oracle, or SQL Server source, copy the source database vendor’s JDBC driver into [Liferay Home]/tools/portal-tools-db-migration-importer/lib. The tool includes the MariaDB, MySQL, and PostgreSQL drivers.

  3. Export the schema again if it changed since your last export, such as after a patch, a module deployment, or a new virtual instance. Liferay DXP must still be running.

  4. Copy the exported SQL files to the host running the importer if they aren’t already there.

  5. Shut down every Liferay DXP node connected to the source database. Nothing can write to the database while the importer reads from it.

  6. From [Liferay Home]/tools/portal-tools-db-migration-importer, run db_migration_importer.sh with the path of the exported SQL files and the source and target connection settings:

    ./db_migration_importer.sh \
      --path "/directory/" \
      --source-jdbc-url "jdbc:mysql://localhost:3306/schema" \
      --source-user "xyz123" \
      --source-password "xyz123" \
      --target-jdbc-url "jdbc:postgresql://localhost:5432/schema" \
      --target-user "xyz321" \
      --target-password "xyz321"
    

    Keep all exported files in the --path directory, since one run imports every instance. The tool stops before it writes anything to the target database if tables.sql or indexes.sql is absent. Run the command from a restricted account or clear your shell history afterward, because the passwords appear in the history and the process list.

  7. Confirm the import succeeded. Open db_migration_import_report.txt in the --path directory and check that the source and target table and view counts match. The missing target tables and missing target views lists should be empty. When database partitioning is enabled, the report repeats these lines for every partition.

    Important

    Exit code 0 means the run finished without an exception, not that every table was copied.

  8. Back up the PostgreSQL database. This backup is your restore point if the first startup fails.

  9. On every node, point Liferay DXP at the PostgreSQL database. See Configuring a Data Source for the available JDBC configuration methods. If your installation uses a JNDI data source, update that resource instead.

    Remove any hibernate.dialect, custom.sql.function.isnull, or custom.sql.function.isnotnull overrides set for the source database in an override file such as portal-ext.properties, or as LIFERAY_* environment variables. Liferay DXP detects the database from the JDBC connection and sets the dialect and these SQL functions itself.

  10. Start Liferay DXP.

  11. Sign in as an administrator and confirm your sites and content are present, with no database errors in the startup log.

If you run the importer from a script, check the exit code as well as the report. The tool exits 0 on success, 1 on a failed import, and 2 whenever it prints the usage message. Exit 2 covers --help, a missing or invalid option, and an unsupported source or target database. A failed import writes a stack trace to standard error, and a successful one writes db_migration_import_report.txt.

Importer Options

These options are available for db_migration_importer.sh:

OptionRequiredDescription
--path <arg>YesPath of the source SQL files
--source-jdbc-url <arg>YesJDBC URL of the source database
--source-user <arg>YesUser name for the source database
--source-password <arg>YesPassword for the source database user
--target-jdbc-url <arg>YesJDBC URL of the target PostgreSQL database
--target-user <arg>YesUser name for the target PostgreSQL database
--target-password <arg>YesPassword for the target PostgreSQL database user
--jdbc-batch-size <arg>NoJDBC batch size (default 2500)
--jdbc-fetch-size <arg>NoJDBC result set fetch size (default 2500)
--helpNoUsage message, recognized only as the first argument

Appending --help to a complete command runs the import instead of printing the usage message.