Microsoft Dataverse to PostgreSQL: How to Move Your Data
Replicate Microsoft Dataverse to PostgreSQL with Airbyte. Change tracking per table, the app registration steps people miss, deletes, and status code mapping.

Replicating Microsoft Dataverse to PostgreSQL moves the tables behind Dynamics 365 and Power Apps into a database you control, so the data can be queried with SQL, joined against other systems, and read by tools that do not speak the Dataverse Web API. Airbyte handles it with no code, and this connector is better equipped than most: it supports genuine change tracking and replicates deletes.
There is one prerequisite that catches people, and it lives in Power Apps rather than in Airbyte. Incremental sync is only available on tables where change tracking has been switched on.
How does incremental sync actually work?
The Microsoft Dataverse source uses Dataverse's own change tracking feature rather than a cursor column. It sends a request with the change-tracking preference header, and the API returns a delta link on the last page of results. The connector stores that link as state and uses it on the next sync to retrieve only what has changed since.
That is a better mechanism than a timestamp cursor, because it does not depend on the application reliably updating a modified date, and it captures deletions. But it depends entirely on change tracking being enabled for the table, which is a setting in the Power Apps table configuration and is not on by default for every entity.
Tables without change tracking support only full refresh. So before you build, list the tables you intend to replicate and check each one. Enabling it later is straightforward, but discovering the gap after someone has built a report on a table you assumed was incremental is not.
One important limitation on deletes: deleted records carry only the ID. If you are keeping a soft-delete history in Postgres, you will know which record was removed and when you learned about it, but not what it contained at the time. If the deleted content matters for audit purposes, retain the last known version yourself before applying the deletion downstream.
Setting up access in Entra ID
This connector needs an app registration rather than a user account, and the setup spans two admin portals.
In the Azure portal, go to Microsoft Entra ID and create a new app registration, noting the application client ID and the directory tenant ID from the overview page. Under certificates and secrets, create a new client secret and copy its value immediately, because it will not be shown again.
Then, in the Power Platform admin centre, select your environment and add that app registration as an application user under users and permissions, granting it at least read access to the tables you want to sync. This second step is the one people miss. The app registration existing in Entra ID does not give it any access to Dataverse data, and skipping it produces authentication that succeeds and a sync that finds nothing.
The connector uses version 9.2 of the Dataverse Web API and discovers your schema automatically from the entity definitions in your environment, so you do not configure streams by hand.
How Dataverse types land in Postgres
The type mapping is mostly what you would hope. Strings and unique identifiers become strings, DateTime becomes a timestamp with timezone, Integer and BigInt become integers, Boolean stays boolean, and Money, Double, and Decimal all become numbers. Status and State become integers. Anything not in that list defaults to string.
Two of those deserve thought. Money mapping to a general number type means you should check what precision survives into Postgres if you are reconciling financial figures. And Status and State arriving as integers means your Postgres tables hold numeric codes rather than the labels users see in Dynamics. Those labels live in option set metadata, which this connector does not sync, so plan a lookup table in Postgres or expect analysts to be querying status codes.
Virtual fields are excluded from the schema entirely and never synced, which is worth knowing if a field visible in the Dynamics interface never appears in your destination.
The Postgres destination writes each stream to a table in your target schema alongside Airbyte's metadata columns. It is Airbyte-supported with a high reported sync success rate, so the destination side is well-trodden and your attention belongs on change tracking and permissions.
Frequently asked questions
Why can't I select incremental sync for a table?
Change tracking is not enabled on it. Tables without change tracking support full refresh only. Enable it in the table settings in Power Apps.
Authentication works but no data arrives.
The app registration probably has not been added as an application user in your Dataverse environment. Add it in the Power Platform admin centre with read access to the tables you need.
What do deleted records look like?
They carry only the ID. If you need the record's contents for an audit trail, keep the last known version yourself before applying the deletion.
Why are my status fields numbers?
Status and State map to integers, and the option set labels are metadata the connector does not sync. Maintain a lookup table in Postgres if analysts need readable values.
Get your Microsoft Dataverse data into PostgreSQL
Check change tracking table by table, complete both halves of the app registration, and plan a lookup table for status codes. For the same source into a lakehouse, see our guide to Microsoft Dataverse to Databricks. For a relational source into the same database, see MySQL to PostgreSQL.
Integrate with 600+ apps using Airbyte
Move data from 600+ sources into warehouses, lakes, and beyond. Set up pipelines in minutes with pre-built connectors and the Connector Builder.
