Migrate

Migrate SQL Server to PostgreSQL, a Planning Guide

Migrate SQL Server to PostgreSQL, a Planning Guide

A SQL Server to PostgreSQL migration is mostly planning, not data copying. Pick a method that fits your database size and downtime tolerance, map out which objects port cleanly and which T-SQL has to be rewritten as PL/pgSQL, and watch the three traps that sink migrations, data type behavior, procedural logic and collation. When the ready made tools cannot help because the source server is gone or the file is corrupt, Univik reads the SQL Server file directly and exports it, and the step by step sits on the SQL Server to PostgreSQL converter page.

Moving a database from SQL Server to PostgreSQL looks like a copy job and turns out to be a translation job. The rows move in hours. The planning, the logic rewrite and the testing take the weeks. Teams make the switch to drop per core licensing and pick up an open source engine with native JSON, arrays and a permissive licence, but the payoff only lands if the migration is planned rather than rushed. This guide walks the decisions that decide whether yours is smooth or painful, which method to use, what to assess first and the traps that catch people who skipped straight to the data load.

The planning arc, before you touch the data
1
Assess
Inventory objects and dependencies

2
Pick a method
Match size and downtime to a route

3
Plan downtime
Choose a bulk load or a live cutover

4
Migrate
Move schema and data across

5
Validate and cut over
Reconcile, test, then switch

The data load sits at step four. Most of the risk lives in steps one through three.

Where the Real Work Hides

The single factor that decides how hard your migration will be is where your business logic lives. If it sits in the database as stored procedures, triggers and functions, every one of those objects is a small rewrite from T-SQL into PL/pgSQL, and that is the bulk of the work. If the logic lives in the application code and the database is just storage, the move is far lighter, a matter of new connection strings, a driver swap and a few syntax adjustments.

So the opening question is less about tooling and more about how tightly your application is wired into SQL Server. Inventory the stored procedures, views, triggers and functions before anything else, then note the dependencies that hide outside them, linked servers, cross database queries and the way each application reaches the data. That count, more than the row count, tells you the real size of the job. The data transfer itself is the quick part. Everything around it is where the time goes.

Pick a PostgreSQL Migration Method

There is no single right way to move SQL Server to PostgreSQL. The method follows the database size, the downtime you can afford and whether the source server is even reachable. Three broad routes cover most cases.

Three routes, by what your migration needs

Assisted conversion
AWS SCT converts the schema and objects and hands you an assessment report, then DMS moves the data. Good for a live server and a cloud target.

Replicated cutover
AWS DMS or a change data capture pipeline streams changes for near zero downtime. Built for large or always on databases.

File first export
Read the SQL Server file straight to CSV, then load with COPY. The route that works when the server is offline, detached or corrupt.

Size and downtime point to a route. A missing or damaged source rules out the first two and leaves the file first export.

A small database with a live server and a maintenance window suits an assisted one time load. A large database that cannot go down needs replication so the two systems run in parallel during cutover. A server that is already gone, or a file that will not attach, rules out both of those and leaves reading the file directly.

The Tools You Will Weigh

The product page compares Univik against live connection tools in general. Here are the actual named options and where each one fits, so you can choose with your eyes open.

AWS SCT and DMS are the assisted path for a cloud target. The Schema Conversion Tool connects to your SQL Server, converts the schema and code objects and produces an assessment report that names what it could not convert automatically. The Database Migration Service then moves the data with change data capture for minimal downtime. This is the heavyweight route into Amazon RDS or Aurora PostgreSQL. Note one sharp edge, AWS SCT does not carry collations across on its own, so case sensitivity is yours to sort out.

pgloader is an open source command line tool that reads a live SQL Server, builds the target schema and streams the rows into PostgreSQL with COPY, casting types along the way. It shines on small to mid sized databases with simple schemas and little procedural code. It wants the source server online and a comfort with the terminal, and the full option set lives in its documentation.

Babelfish for Aurora PostgreSQL works differently, it runs a T-SQL compatibility layer on top of Postgres so existing applications keep speaking T-SQL. It can cut the rewrite work when the application is deeply tied to SQL Server syntax, at the cost of running on a specific Aurora setup.

One tool that will not help here is Microsoft SSMA. The SQL Server Migration Assistant moves other engines into SQL Server, not the reverse, so it has no path out to PostgreSQL. It is an easy wrong turn to take, since the name suggests otherwise.

For a large, procedure heavy database, commercial migration toolkits automate more of the T-SQL rewrite than the free tools manage, in exchange for a licence fee. They earn that fee when there are hundreds of objects to convert by hand.

Every assisted or live tool above needs a running SQL Server to read from. That is the gap the file first route fills, and the point of the section further down.

Assess What Ports and What Does Not

Before you move anything, sort your database into what converts cleanly and what needs a human. Table structures, the rows inside them, keys, indexes and the everyday data types cross over with little fuss. The effort concentrates in the procedural layer. Anything holding T-SQL, the stored procedures, views and triggers, has no direct equivalent and gets ported to PL/pgSQL by hand.

Run an assessment pass with AWS SCT early, even if you plan to migrate a different way, because its report names the objects that will need attention. That list is your migration backlog. A database that is all tables and data is a weekend. A database with hundreds of procedures is a project. The converter page lays out the exact data type mapping and the syntax notes, so use that as your reference while you rebuild the schema, and keep this page for the plan around it.

The Three Traps That Break Migrations

Most migrations that go wrong fail on the same three things. None of them show up when you test with a handful of rows, which is exactly why they bite later.

The three traps, in order of how often they bite
1. Data type behavior, not just names
A type can map on paper and behave differently in practice. MONEY can round where NUMERIC keeps full precision, and a SQL Server datetime carries no time zone while a PostgreSQL timestamptz does. Test the edge values, not the average row.

2. T-SQL logic has to be rewritten
Procedures, views and triggers do not port. PL/pgSQL is capable but syntactically different, and every piece of business logic in the database is manual work to translate and retest.

Aa
3. Collation and case sensitivity
SQL Server is case insensitive by default. PostgreSQL folds unquoted identifiers to lowercase and quoted ones are case sensitive, and collation rules differ. Many conversion tools will not carry collations across, so plan for it.

Each trap survives a small test and surfaces at full scale, so prove them out on real data and real queries before cutover.

The collation trap is the sneakiest of the three because it changes query results rather than throwing an error. A query that matched Smith and SMITH in SQL Server returns nothing in PostgreSQL once comparisons turn case sensitive. The fix is to force both sides of a text comparison to the same case, or to store those columns in a case insensitive type like citext so the old matching carries over. The data type traps are quieter still. A SQL Server datetime stores time in ticks of 1/300th of a second, so every value ends in .000, .003 or .007. Those odd endings carry straight into PostgreSQL while new rows use microsecond precision, and a report that groups on the exact timestamp can split records you expected to match. There is also the identity question. In Postgres an old IDENTITY column turns into a generated identity or a sequence, and that sequence has to be reseeded to the current maximum after the data lands or the first insert collides.

Downtime and the Cutover

How much downtime you can take shapes the whole migration. A one time bulk load is simpler to run and validate, but the source is frozen or offline while it happens, so it fits databases that can take a maintenance window. When an outage is not an option, you move to logical replication or change data capture, where a tool like AWS DMS or Debezium streams changes from SQL Server into PostgreSQL while both run, and you flip the application over once they are in sync.

Two ways to handle the cutover

One time bulk load
Simpler to run and check. The source is frozen while it happens, so you need a maintenance window. Best when the database can go down for a few hours.

Replicated cutover
Change data capture streams updates while both databases run, so downtime shrinks to the switch itself. More moving parts to set up and watch. Built for systems that cannot pause.

Neither wins outright. The outage you can afford picks the method.

Plan the cutover as its own step with a rollback ready. Pick the moment, point the application at PostgreSQL, then watch the row counts and error rates while keeping the SQL Server source untouched until you are confident. A migration you can rehearse on a staging copy and repeat is one you can trust. A single unrepeatable attempt against production is how weekends get ruined.

Validate Before You Trust It

Data landing in PostgreSQL is not the same as a finished migration. The validation is what tells you it actually worked, and it runs on a short, concrete checklist.

  1. Compare row counts table by table between the two databases.
  2. Run checksum or hash comparisons to catch values that changed in transit.
  3. Spot check real queries and reports against known results.
  4. Reseed identity sequences, rebuild indexes and refresh statistics with VACUUM ANALYZE.

Then test the application against PostgreSQL, not just the database in isolation, because the collation and type traps show up in how the app queries the data. Only once the counts match, the spot checks pass and the application behaves do you retire the SQL Server source. Keep it around read only for a while even then, a cheap insurance policy against the bug you did not catch.

When the Source Is Offline or Corrupt

Every assisted and replicated method above assumes a running SQL Server to connect to. Plenty of real migrations do not have one. The server was decommissioned and all that survives is an MDF file, or the database is detached or corrupt and will not attach. In those cases the connection based tools have nothing to connect to and simply stop.

That is where reading the file directly is the only route left. Univik opens the SQL Server file itself, MDF, NDF or BAK, with no instance running, and turns each table into a CSV ready for a PostgreSQL COPY load, plus a schema script to rebuild the structure. Because it parses the file at the page level it can recover tables from a database too damaged or detached for a live tool to touch. The same idea underpins opening an MDF without SQL Server at all. The full four step walk through and the complete data type table live on the SQL Server to PostgreSQL converter page. If the file is badly damaged, repair it with SQL Database Recovery first, and for the wider picture of moving off SQL Server see the SQL Server migration guide. Moving to MySQL instead? The same file first idea is covered on SQL Server to MySQL.

Frequently Asked Questions

How Long Does a SQL Server to PostgreSQL Migration Take?

The data copy is fast, the planning and testing are not. A database under 10GB with simple schema can move in a few days, 10 to 100GB takes one to two weeks, and larger or procedure heavy databases stretch into weeks or months. The variable is not size so much as how much T-SQL logic has to be rewritten as PL/pgSQL and validated.

Which Tool Is Best for Migrating SQL Server to PostgreSQL?

It depends on your situation. AWS SCT converts the schema and flags the hard parts in an assessment report, pgloader suits small to mid databases with light procedural code and pairing SCT with AWS DMS handles large cloud migrations with minimal downtime. When the source server is gone or the file is corrupt, a file first tool that reads the database directly is the only option that still works.

Do Stored Procedures Migrate Automatically to PostgreSQL?

Not fully. Tables and data convert cleanly, but the stored procedures, views and triggers carry T-SQL that Postgres has no way to execute as written. Assisted tools translate the simple ones and flag the rest, so complex procedures are manual work to rewrite in PL/pgSQL and retest. The volume of that logic is the biggest driver of how long a migration takes.

What Are the Biggest Risks in a PostgreSQL Migration?

Three traps cause most failures, data type behavior that differs even when names match, T-SQL logic that has to be rewritten and collation with case sensitivity. The last one is the sneakiest because it changes query results instead of throwing an error, since PostgreSQL treats identifier case differently from SQL Server. Test all three on real data before cutover.

Can I Migrate to PostgreSQL with No Downtime?

Close to none, with the right method. Logical replication or change data capture tools like AWS DMS or Debezium stream changes from SQL Server into PostgreSQL while both run, so you cut over once they are in sync. A one time bulk load is simpler but needs a maintenance window where the source is frozen. The choice comes down to how much outage the application can take.

How do I Migrate a Database When the SQL Server Is Gone?

Read the file directly. Connection based tools need a running server, so a decommissioned, detached or corrupt source stops them cold. A file first approach opens the MDF, NDF or BAK on disk and exports the tables to CSV for a PostgreSQL COPY load, with no instance involved. Univik works this way, and the steps are on the SQL Server to PostgreSQL converter page.

Source server gone, or the file will not attach?

Univik reads the SQL Server file offline and exports every table to CSV that PostgreSQL loads with COPY, even from a detached or corrupt database. The full walk through and the data type table are on the converter page.



See the File First Converter

About the Author

Written and maintained by Leena Taylor Paul and the Univik team, developers of Windows data conversion and recovery software since 2013. The migrations that reach us are the awkward ones. A SQL Server switched off before anyone exported the data, or a database too corrupt for AWS SCT or pgloader to reach. That file first corner is the part we have spent years getting right. Last verified July 2026. Planning a move and stuck on the source? Contact our support team.