Moving an existing PostgreSQL application to a managed database service can reduce infrastructure management, but database migration involves more than changing a connection string.
Azure HorizonDB is Microsoft's cloud-native, PostgreSQL-compatible database service. It separates compute and storage, supports read replicas, and includes capabilities for high-throughput transactional workloads and AI-powered applications.
Because it uses PostgreSQL, existing applications can connect through familiar PostgreSQL drivers, clients, and SQL syntax. However, PostgreSQL compatibility does not mean every database configuration, extension, operational feature, or application assumption will work exactly as before.
Before moving an application, teams should examine PostgreSQL versions, extensions, authentication, network connectivity, connection pooling, backups, performance, and operational requirements.
There is another important consideration: Azure HorizonDB is currently in public preview. Its feature availability and limitations should be evaluated carefully before selecting it for a production migration.
This article explains what to check before migrating an existing PostgreSQL application and how to validate the migration using a practical approach.
Understand How Azure HorizonDB Works
Traditional PostgreSQL deployments generally keep database compute and storage closely connected. Scaling compute, handling replication, and managing storage can require additional infrastructure planning.
Azure HorizonDB uses a different architecture.
It separates the compute layer from the storage layer. The compute layer runs PostgreSQL and processes queries, while the storage layer maintains database data and write-ahead logs.
The service also uses a database-as-a-log architecture. Changes are recorded in a durable write-ahead log (WAL), which is used to maintain the database state.
This design provides several capabilities:
- Compute resources can be scaled independently of storage.
- Storage grows independently as database data increases.
- Read replicas can share the underlying storage.
- The service supports a primary endpoint for writes and a read-only endpoint for read workloads.
- Storage is designed for zone resilience.
These architectural differences can affect how applications scale and how database operations behave.
For example, an application that performs frequent reporting queries may benefit from routing read-only traffic to the read endpoint rather than sending every query to the primary.
However, the application must correctly distinguish between read and write operations.
Check PostgreSQL Version Compatibility
The first step in any database migration is identifying the PostgreSQL version used by the existing application.
Run the following query against the current database:
SELECT version();
You can also retrieve the server version number:
SHOW server_version;
For example, the output might identify PostgreSQL 15 or PostgreSQL 16.
Azure HorizonDB's current documentation identifies PostgreSQL 17 as its supported engine version. Confirm the available version in your target environment before planning the migration.
Version differences can affect:
- SQL syntax and behavior.
- Query planner decisions.
- Available built-in functions.
- Extension compatibility.
- Index behavior.
- Authentication and security settings.
- Application drivers and ORM behavior.
Do not assume that an application running on an older PostgreSQL version will behave identically after migration.
Review Version-Specific Features
Suppose an application uses a PostgreSQL feature introduced in a newer release.
If the target database does not support that feature, the application may fail during deployment or runtime.
Review the official PostgreSQL release notes for the versions between your source and target environments.
Also inspect database functions, stored procedures, triggers, and SQL queries that may depend on version-specific behavior.
Inventory PostgreSQL Extensions
PostgreSQL extensions add functionality that is not necessarily available in the core database engine.
Applications may depend on extensions for:
- UUID generation.
- Full-text search.
- Geographic queries.
- Vector similarity search.
- Monitoring and query analysis.
- Specialized data types.
Before migration, list the extensions installed in the existing database:
SELECT
extname,
extversion
FROM pg_extension
ORDER BY extname;
For example, an application using vector search might depend on pgvector.
A database migration can fail or produce unexpected behavior if an extension is missing, unsupported, or available in a different version.
Check Extension Availability on HorizonDB
Do not rely only on the source database's extension list.
Check the extensions supported by the target HorizonDB environment and confirm whether they can be enabled.
For extensions that require explicit configuration, review the service's extension management instructions.
You should also test extension-dependent queries after migration.
For example:
SELECT
extname,
extversion
FROM pg_extension
WHERE extname = 'vector';
This verifies whether the vector extension is installed in the target database.
If an extension is unavailable, identify an alternative before moving production data.
Review Database Roles and Permissions
Database users and permissions are another important migration area.
A PostgreSQL application may use several database roles for different responsibilities:
- Application connections.
- Read-only reporting.
- Database administration.
- Background workers.
- Migration scripts.
List existing roles using:
SELECT
rolname,
rolsuper,
rolcreatedb,
rolcreaterole,
rolcanlogin
FROM pg_roles
ORDER BY rolname;
Review role memberships and object-level permissions as well.
A role that works in a self-managed PostgreSQL environment may not have the same privileges in a managed database service.
Managed services generally restrict certain administrative operations because the provider controls the underlying infrastructure.
Avoid Depending on Superuser Access
Some applications and migration scripts assume that the database user has unrestricted privileges.
This can cause problems when moving to a managed platform.
Review scripts that attempt to:
- Create superuser roles.
- Change server-level configuration.
- Access operating-system files.
- Manage background processes.
- Modify restricted system objects.
Replace unnecessary administrative dependencies with supported database permissions.
Use the principle of least privilege when creating application roles.
Review Authentication and Connection Security
Existing PostgreSQL applications commonly connect using a username and password stored in an environment variable or configuration file.
Azure HorizonDB supports standard PostgreSQL connectivity and provides authentication and security capabilities that should be reviewed before migration.
The service also supports Microsoft Entra ID integration.
Before moving the application, decide how database identities will be managed.
Check the following:
- Whether the application will use password-based authentication or Microsoft Entra ID.
- Whether the selected driver supports the chosen authentication method.
- Whether TLS is configured correctly.
- Whether credentials are stored securely.
- Whether database roles have only the required permissions.
- Whether development and production environments use separate credentials.
Review the Connection String
A typical PostgreSQL connection string looks like this:
Host=database.example.com;
Port=5432;
Database=application_db;
Username=app_user;
Password=your_password;
SSL Mode=Require;
The actual HorizonDB endpoint, authentication configuration, and TLS requirements must come from your cluster configuration.
Do not copy the source database's hostname or connection settings into the new environment without checking them.
For example, a .NET application using Npgsql can continue using a standard PostgreSQL connection string, provided the selected authentication and TLS settings are supported.
using Npgsql;
var connectionString =
Environment.GetEnvironmentVariable("DATABASE_CONNECTION");
await using var connection =
new NpgsqlConnection(connectionString);
await connection.OpenAsync();
Console.WriteLine("Database connection successful.");
Keep credentials outside source code. Use a secure configuration or secrets-management service to supply the connection string at runtime.
Understand the Primary and Read-Only Endpoints
Azure HorizonDB provides different endpoints for read-write and read-only workloads.
The primary endpoint directs connections to the writable primary replica.
The read-only endpoint distributes connections across readable replicas.
This distinction is important when migrating applications that already use read replicas.
Consider an e-commerce application that performs:
- Order creation.
- Payment updates.
- Product searches.
- Order history queries.
- Sales reports.
Write operations should use the primary endpoint.
Read-only operations that can tolerate replica visibility behavior may use the read-only endpoint.
A simple application configuration might look like this:
DATABASE_WRITE_CONNECTION=
DATABASE_READ_CONNECTION=
The application can then select the appropriate connection based on the operation.
For example:
public sealed class DatabaseSettings
{
public string WriteConnection { get; set; } = string.Empty;
public string ReadConnection { get; set; } = string.Empty;
}
Use the write connection for transactions that modify data and the read connection for suitable reporting or lookup queries.
Do not automatically route every SELECT statement to a read replica.
Some reads must observe the latest committed write. For example, after a customer places an order, the application may immediately retrieve that order to display confirmation.
If that query goes to a replica before the change becomes visible there, the application may return stale or unexpected results.
Design read routing around consistency requirements, not just SQL command type.
Check Connection Pooling Requirements
Connection pooling is particularly important for applications that create many short-lived database connections.
For example, a web application running multiple application instances may create more database connections as traffic increases.
If each instance opens too many connections, the database can become overloaded.
Review:
- Maximum connections per application instance.
- Connection pool size.
- Connection lifetime.
- Idle connection handling.
- Connection retry behavior.
- Total connections across all application instances.
Azure HorizonDB's current preview documentation lists built-in PgBouncer connection pooling as unavailable.
If your application depends on PgBouncer, plan for an external connection pooler or review another supported connection-management approach.
Do not assume that a pooling configuration from an existing PostgreSQL service will transfer directly.
Test connection behavior under realistic application load before migration.
Review Network Connectivity
Network configuration is often one of the first issues encountered during a managed database migration.
Your existing PostgreSQL server may be accessible through:
- A private network.
- A virtual machine.
- A Kubernetes cluster.
- A corporate VPN.
- A public endpoint with firewall restrictions.
Azure HorizonDB supports private connectivity through Private Link. However, its current preview documentation lists virtual network injection as unavailable.
This distinction matters when an organization has strict network architecture requirements.
Before migration, verify:
- Whether the application environment can reach the HorizonDB endpoint.
- Whether private endpoint connectivity is configured.
- Whether DNS resolves the database endpoint correctly.
- Whether firewall rules permit the required traffic.
- Whether TLS connections succeed.
- Whether administrative access follows the organization's security policies.
Test connectivity from the actual application environment rather than relying only on a developer workstation.
A successful connection from a laptop does not prove that a production application running in a separate network can connect.
Plan the Data Migration
Once compatibility and connectivity have been checked, plan how to transfer the database.
For a straightforward migration, PostgreSQL's pg_dump and pg_restore utilities can be used.
Step 1: Create a Database Backup
Run the following command against the source database:
pg_dump \
-h source-db.example.com \
-U migration_user \
-d application_db \
-F c \
-f application_db.backup
The -F c option creates a custom-format backup that can be restored using pg_restore.
Protect the backup file because it may contain sensitive application data.
Step 2: Restore the Database
After creating the target database and confirming connectivity, restore the backup:
pg_restore \
-h target-db.example.com \
-U migration_user \
-d application_db \
--no-owner \
application_db.backup
The --no-owner option can be useful when source role ownership does not exist in the target environment.
However, ownership and permissions must be recreated according to the target database's role configuration.
The exact restore options depend on the source database, target permissions, extensions, and migration requirements.
Step 3: Validate the Restored Data
Do not treat a successful restore command as proof that the migration is complete.
Compare important database objects and data.
For example:
SELECT COUNT(*) FROM customers;
SELECT COUNT(*) FROM orders;
SELECT COUNT(*) FROM products;
Run the same queries against the source and target databases.
For large tables, also consider checking primary keys, important aggregates, and business-specific data relationships.
A complete validation process should cover:
- Tables and indexes.
- Views and materialized views.
- Sequences.
- Functions and procedures.
- Triggers.
- Constraints.
- Roles and permissions.
- Extensions.
- Application-specific data rules.
For applications that cannot tolerate a long write outage, a simple dump-and-restore process may not be sufficient. Evaluate a migration approach that supports change capture or another controlled synchronization method.
Review Backup and Disaster Recovery Requirements
Database backup and recovery requirements should be evaluated before selecting a managed database platform.
Azure HorizonDB's current preview documentation lists seven-day backup retention and identifies several capabilities that are not yet available.
These include:
- Configurable backup retention.
- Cross-region read replicas.
- Customer-managed encryption keys.
- Configurable maintenance windows.
- Long-term backup retention.
These limitations may affect organizations with strict disaster recovery, compliance, or data retention requirements.
For example, an organization that requires 30 days of configurable backup retention should verify whether the current HorizonDB preview meets that requirement.
Similarly, if the application requires cross-region disaster recovery, confirm the available recovery options rather than assuming that zone resilience provides regional disaster recovery.
Zone resilience and cross-region disaster recovery solve different problems.
Before migration, document:
- Recovery Point Objective (RPO).
- Recovery Time Objective (RTO).
- Required backup retention.
- Regional recovery requirements.
- Restore testing frequency.
- Data encryption requirements.
A backup strategy is useful only when the team has tested that the data can actually be restored.
Test Application Performance Before Switching Traffic
PostgreSQL compatibility does not guarantee identical performance.
Different database architectures, compute configurations, indexes, query plans, and workload patterns can produce different results.
Before moving production traffic, execute representative workloads against HorizonDB.
Focus on:
- Frequently executed SQL queries.
- Complex joins.
- Large table scans.
- Transaction-heavy operations.
- Bulk inserts and updates.
- Concurrent connections.
- Reporting queries.
- Long-running transactions.
Use EXPLAIN and EXPLAIN ANALYZE to investigate query execution.
For example:
EXPLAIN ANALYZE
SELECT
order_id,
customer_id,
total_amount
FROM orders
WHERE customer_id = 1001
ORDER BY created_at DESC
LIMIT 20;
Compare execution plans and execution times between environments.
Also test under realistic concurrency.
A query that performs well with one connection may behave differently when hundreds of requests execute simultaneously.
Do not rely on a small set of successful manual queries as the only performance validation.
Common Migration Mistakes
Mistake | Why it causes problems | Better approach |
|---|
Assuming complete PostgreSQL feature parity | Some extensions and administrative features may be unavailable | Check the supported feature list |
Changing only the connection string | Authentication, TLS, and network settings may differ | Validate connectivity and security separately |
Ignoring read replica behavior | Applications may read data before it becomes visible on a replica | Route consistency-sensitive reads to the primary |
Ignoring connection pooling | Application instances may create excessive connections | Review pooling requirements and alternatives |
Skipping data validation | Missing or inconsistent data can reach production | Compare important tables and business rules |
Ignoring backup retention | Recovery requirements may not be satisfied | Verify backup and restore capabilities |
Testing only simple queries | Complex workloads may behave differently | Run representative load tests |
Migrating without a rollback plan | Failed deployments can extend application downtime | Define rollback conditions before cutover |
Advantages and Disadvantages of Moving to Azure HorizonDB
Advantages
- PostgreSQL-compatible connectivity can reduce application changes.
- Compute and storage can scale independently.
- Read replicas support additional read capacity.
- The architecture is designed for zone-resilient storage.
- Managed infrastructure reduces some database administration work.
- Native AI and vector capabilities can support modern application workloads.
- Integration with Microsoft services can simplify certain Azure-based architectures.
Disadvantages
- The service is currently in preview, so production suitability must be assessed carefully.
- Some PostgreSQL extensions or administrative capabilities may not be available.
- Built-in PgBouncer connection pooling is currently unavailable.
- Cross-region read replicas are not currently available.
- Backup retention and maintenance configuration have preview limitations.
- Migration still requires application, data, security, and performance validation.
Summary
Moving a PostgreSQL application to Azure HorizonDB should begin with a compatibility and operational assessment, not a connection-string change.
Check the PostgreSQL version, extensions, roles, authentication, network configuration, connection pooling, backup requirements, and read-replica behavior before transferring data.
After the migration, validate database objects, compare important data, test application queries, and run realistic workloads before directing production traffic to the new database.
Most importantly, evaluate the current preview limitations against your organization's availability, security, compliance, and disaster recovery requirements.
A successful migration is not simply one in which the application connects to the new database. It is one in which the application continues to behave correctly, data remains consistent, and the database platform meets the operational requirements of the workload.
Join the conversation! Your thoughts help the community grow.