PostgreSQL → SQL Server / Azure SQL
Step-by-step procedure for migrating a PostgreSQL 13+ database to SQL Server 2019+ or Azure SQL Database using Endrias Bridge, including prerequisites, type-conversion guidance, and post-migration validation.
Overview & Scope
This SOP covers a full copy (schema + data) from a PostgreSQL 13+ source into a SQL Server 2019+ or Azure SQL Database target using the Endrias Bridge GUI. All tables in the selected schema are migrated; PostgreSQL-specific types (BOOLEAN, SERIAL, UUID, JSONB, ARRAY, PostGIS) are converted automatically, with warnings logged for any lossy mappings.
Prerequisites — Source (PostgreSQL)
Run the following checks and grants on the source PostgreSQL server before starting the migration wizard:
-- Check WAL level (must be 'logical' for CDC mode; restart required to change)
SHOW wal_level;
-- Check replication slot capacity (must be >= 2 for CDC mode)
SHOW max_replication_slots;
-- Recommended: set in postgresql.conf
-- wal_keep_size = 51200 (MB)
-- Grant migration user access
GRANT CONNECT ON DATABASE EndriasBridge TO MigrationUser;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO MigrationUser;
-- CDC mode only (requires REPLICATION role):
-- ALTER ROLE MigrationUser REPLICATION;
| Requirement | Verify |
|---|---|
| PostgreSQL 13+ accessible from migration host | Verify |
wal_level = logical — required for CDC; full-copy does not need it (restart to change) | SHOW wal_level; |
max_replication_slots >= 2 | SHOW max_replication_slots; |
wal_keep_size = 51200 (MB) in postgresql.conf, or active replication slot | Check conf |
MigrationUser has CONNECT + SELECT on all tables in EndriasBridge | Run grants above |
| TCP port 5432 open from migration host to PostgreSQL server | Network check |
Prerequisites — Target (SQL Server / Azure SQL)
| Requirement | Verify |
|---|---|
SQL login MigrationUser with db_owner on target database EndriasBridgeTarget | Verify |
| ODBC Driver 17 for SQL Server installed on migration host | Verify |
| TCP 1433 open from migration host to target SQL Server / Azure SQL | Network check |
Target database EndriasBridgeTarget pre-created, or use "Auto-create" checkbox in Migration Projects Step 3 | Create DB |
| Azure SQL only: Add migration host public IP to server firewall rules in Azure Portal | If Azure SQL |
sql-target.database.windows.net. Enable
Allow Azure services and resources to access this server in the
Azure Portal firewall settings if the migration host is also in Azure.Configure Connections
Open Endrias Bridge and navigate to Migration Projects. Create a new project and fill in both connection blocks as shown:
SOURCE DATABASE
TARGET DATABASE
Run Assessment
Switch to the Assessment tab and click Run Assessment. Endrias Bridge will enumerate all tables and columns on the PostgreSQL source and report type-compatibility warnings before any data is moved.
SOURCE OBJECTS
public.users 19,700 rows
public.orders 88,200 rows
public.products 4,300 rows
public.events 440,000 rows
… (40 more)
COMPATIBILITY WARNINGS
• users.id: SERIAL → INT IDENTITY(1,1)
• orders.uid: UUID → UNIQUEIDENTIFIER
• products.metadata: JSONB → NVARCHAR(MAX)
• events.tags: TEXT[] → NVARCHAR(MAX) [WARNING]
• … (full list per table)
Select Tables
Return to Migration Projects. Click
Load Tables from Source. All 44 tables are selected by default.
Deselect any tables you want to skip. Enable Auto-create target DB
if EndriasBridgeTarget does not yet exist on the target server.
geometry/geography columns will
migrate, but those columns become NVARCHAR(MAX) WKT text. If spatial
queries are required on the SQL Server target, plan a post-migration conversion
to SQL Server's native spatial types (geometry/geography).Start Migration & Monitor
Click Start Migration. The migration log updates live as each table's schema is created and rows are bulk-copied. Review all WARNING lines before closing the panel.
--- Done --- appears
and the total row count matches expectations from the source.Verify & Export Report
- Click Verify Data Integrity — compares source vs. target row counts for every migrated table and logs any mismatches.
- Manually spot-check rows in tables flagged with WARNING (ARRAY, JSONB, geometry columns).
- Click Export Report (enabled once migration finishes) to save an HTML summary of all tables created, rows copied, type conversions applied, and warnings generated.
- Archive the report with the project change ticket for sign-off.
Post-Migration Tasks
Complete the following tasks on the target SQL Server / Azure SQL after verifying row counts:
-- 1. Reset IDENTITY seeds to the current max migrated value
DBCC CHECKIDENT ('EndriasBridgeTarget.dbo.users', RESEED);
-- Repeat for every table with an IDENTITY column.
-- 2. JSONB columns are stored as NVARCHAR(MAX) — update app queries
-- PostgreSQL: WHERE metadata->>'key' = 'value'
-- SQL Server: WHERE JSON_VALUE(metadata, '$.key') = 'value'
-- or use OPENJSON() for multi-row extraction
-- 3. Array columns serialized to NVARCHAR(MAX) — notify application team
-- Application must parse the serialized text format.
-- 4. Rebuild fragmented indexes after bulk insert
ALTER INDEX ALL ON dbo.users REBUILD;
-- Repeat for each migrated table.
-- 5. Update statistics
UPDATE STATISTICS dbo.users;
| Post-Migration Task | Priority |
|---|---|
Reset IDENTITY seeds: DBCC CHECKIDENT for all identity tables | Required |
Update JSONB app queries to use JSON_VALUE() / OPENJSON() | Required |
| Notify application team of serialized ARRAY columns (NVARCHAR(MAX)) | Required |
| Update BOOLEAN literal comparisons (TRUE/FALSE → 1/0) | Required |
| Rebuild indexes on all migrated tables | Recommended |
| Validate PostGIS geometry columns converted to WKT NVARCHAR(MAX) — convert if spatial queries needed | If applicable |
| Scale target DTUs/vCores back to steady-state after migration completes | Recommended |
Known Issues
| Issue | Detail | Action Required |
|---|---|---|
| ARRAY types | All PostgreSQL array columns are serialized to NVARCHAR(MAX). A WARNING is logged for every affected column. SQL Server has no native array type. |
Update application array-parsing logic |
| JSONB / JSON | Stored as NVARCHAR(MAX) (JSON text is preserved verbatim). Use JSON_VALUE() / OPENJSON() on SQL Server. |
Update application queries |
| BOOLEAN → BIT | TRUE/FALSE become 1/0. Application string literals like 'true' must be updated. |
Update literal comparisons |
| SERIAL / BIGSERIAL | Become INT IDENTITY(1,1) / BIGINT IDENTITY(1,1). Identity seeds may diverge after bulk insert. |
Run DBCC CHECKIDENT post-migration |
| UUID → UNIQUEIDENTIFIER | Values preserved. PostgreSQL stores lowercase hex; SQL Server stores uppercase. No functional difference. | None — cosmetic only |
| CIDR / INET | Stored as NVARCHAR(45) (text representation of IP/subnet). |
Update IP-range queries if any |
| PostGIS geometry / geography | Stored as NVARCHAR(MAX) WKT via .ToString(). Lossy — spatial operations not available without post-migration conversion. |
Convert WKT to SQL Server spatial types if needed |
| Case sensitivity | All identifiers lowercased. PostgreSQL public schema maps to dbo; other schemas are preserved. |
Review schema-qualified queries |
| Standalone sequences | Standalone PostgreSQL sequences (not tied to SERIAL) are not migrated. Only IDENTITY columns are created. | Recreate sequences manually if needed |
Type Conversions Applied (PostgreSQL → SQL Server)
| Source (PostgreSQL) | Target (SQL Server) | Note |
|---|---|---|
| BOOLEAN | BIT | TRUE/FALSE → 1/0 |
| SMALLINT | SMALLINT | |
| INTEGER | INT | |
| BIGINT | BIGINT | |
| SERIAL | INT IDENTITY(1,1) | Run DBCC CHECKIDENT post-migration |
| BIGSERIAL | BIGINT IDENTITY(1,1) | |
| REAL | REAL | |
| DOUBLE PRECISION | FLOAT | |
| NUMERIC(p,s) | DECIMAL(p,s) | |
| CHAR(n) | NCHAR(n) | |
| VARCHAR(n) | NVARCHAR(n) | |
| TEXT | NVARCHAR(MAX) | |
| BYTEA | VARBINARY(MAX) | |
| DATE | DATE | |
| TIME | TIME | |
| TIMESTAMP | DATETIME2 | |
| TIMESTAMPTZ | DATETIMEOFFSET | UTC offset preserved |
| UUID | UNIQUEIDENTIFIER | |
| JSON / JSONB | NVARCHAR(MAX) | Use JSON_VALUE / OPENJSON on SQL Server |
| ARRAY (any) | NVARCHAR(MAX) | Serialized — WARNING logged |
| CIDR / INET | NVARCHAR(45) | Text representation |
| geometry / geography | NVARCHAR(MAX) | WKT via .ToString() — lossy |
| OID / XML | NVARCHAR(MAX) |