TL;DR
Microsoft's integration overview for finance and operations apps publishes a table of six integration patterns, and two of those six rows are containers holding several documented surfaces each. This is the expansion, the synchronous-versus-asynchronous split, Microsoft's own volume rule of thumb and sizing examples with the caveat it attaches to them, and the one documented constraint that decides each pattern.
Microsoft names six Dynamics 365 integration patterns. Which for which job?
Microsoft's integration overview for finance and operations apps opens with "The following table lists the integration patterns that are available" and then lists six. Two of those six rows are containers, and unpacking them off their own pages is what turns a list into a decision.
Here is the expansion, the synchronous-versus-asynchronous split, Microsoft's published volume rule of thumb, and the one documented constraint that decides each pattern. It assumes the pillar on the write path and does not restate it.
The six, as Microsoft lists them
Reproduced from that page, in Microsoft's order, with Microsoft's names character-exact.
- Power Platform integration — The documentation Microsoft links it to: Microsoft Power Platform integration with finance and operations apps — the shared data layer with Dataverse · Status:
[GA] - OData — The documentation Microsoft links it to: Open Data Protocol (OData) — the REST endpoint over every entity marked IsPublic · Status:
[GA] - Batch data API — The documentation Microsoft links it to: Two pages: Recurring integrations and Data management package REST API · Status:
[GA] - Custom service — The documentation Microsoft links it to: Custom service development — X++ classes on a SOAP endpoint and a JSON endpoint · Status:
[GA] - Consume external web services — The documentation Microsoft links it to: Consume external web services — the ERP as the calling client, not the callee · Status:
[GA] - Excel integration — The documentation Microsoft links it to: Office integration overview — the Excel Data Connector add-in over OData · Status:
[GA]
None of the six rows carries a preview marker on that page, which is where the [GA] labels come from — the absence of a marker, not a status stamp. The page's ms.date is 2026-03-09. One deployment fact sits directly under the table and is easy to skim past: "For on-premises deployments, the only supported API is the Data management package REST API."
Two of those six rows are containers
Batch data API points at two documented APIs, and the Data management package REST API page says so in its own words: "Two APIs support file-based integration scenarios: the Data management framework's package API and the recurring integrations API."
Power Platform integration is the wider one. Its overview page names four things under the heading Integration tools for data and business logic: "Together, virtual entities, dual-write, business events, and data events make up the shared data layer for the convergence of finance and operations apps and the Dataverse platform. They're complementary technologies that work together."
So the working list is longer than six. Counting Microsoft's named surfaces rather than its rows — our count, off Microsoft's pages, not a Microsoft number:
- Virtual entities — Sits under: Power Platform integration · Microsoft's own purpose, quoted: "act as a virtual data source in Dataverse"
- Dual-write — Sits under: Power Platform integration · Microsoft's own purpose, quoted: "near-real-time synchronous copying of data" for overlapping entities
- Business events — Sits under: Power Platform integration · Microsoft's own purpose, quoted: "respond to events that occur in finance and operations apps"
- Data events — Sits under: Power Platform integration · Microsoft's own purpose, quoted: "occur when there's a change to a record in the application data"
- Recurring integrations — Sits under: Batch data API · Microsoft's own purpose, quoted: "the exchange of documents or files between finance and operations and any third-party application or service"
- Data management package REST API — Sits under: Batch data API · Microsoft's own purpose, quoted: "lets you integrate by using data packages"
Add OData, custom service, consume external web services and Excel integration, and our count reaches ten named surfaces behind six published rows. That gap is where architecture reviews go wrong, because two teams comparing "Power Platform integration" are often comparing different things.
Synchronous or asynchronous decides more than the pattern name does
Microsoft's own warning, verbatim, is the one that catches people:
"Before you compare synchronous and asynchronous patterns, be aware that all the REST and SOAP integration application programming interfaces (APIs) can be invoked either synchronously or asynchronously… You can't assume that the caller is blocked when the Open Data Protocol (OData) is used for integration."
The label is about where the work happens, not how your client calls it. OData and custom services are synchronous "because when you call these APIs, business logic runs immediately"; batch data APIs are asynchronous because ImportFromPackage "schedules a batch job to import only a specific data package… and the work is done later in a batch job."
That sets your error handling. Microsoft: "the status of the data import or export isn't pushed to the caller. The caller must poll for the result of the corresponding import or export process."
Microsoft's rule of thumb, and the sizing examples beside it
Read the caveat first. It sits above the pattern table on that page, and therefore above every sizing example below it:
"When providing guidance and discussing scenarios for choosing a pattern, data volume numbers are mentioned. Use these numbers only to gauge the pattern and don't consider them as hard system limits. The absolute numbers vary in real production environments because of different factors—configurations are only one aspect of this scenario."
With that in place, the threshold, verbatim: "here's a rule of thumb: If the volume is more than a few hundred thousand records, use the batch data API for integrations." Microsoft prefixes it by saying the answer "depends on the entity, and on the amount of business logic that is run during import or export."
And the published scenarios, with the values Microsoft gives them. Each is a scenario Microsoft names, not a benchmark:
- Create and update product information from an on-premises third-party application — Real-time data required?: Yes · Peak data volume: 1,000 records per hour (Microsoft footnotes this row: bursts occur) · Recommended pattern: OData
- Read the status of customer orders on a self-hosted portal — Real-time data required?: Yes · Peak data volume: 5,000 records per hour · Recommended pattern: OData
- Approve BOMs (bills of materials — the parts list for a product) from a PLM (product lifecycle management) workflow — Real-time data required?: Yes · Peak data volume: 1,000 records per hour · Recommended pattern: OData action (
BOMBillOfMaterialsHeaderEntity::approve) - Look up on-hand inventory from a scheduling application — Real-time data required?: Yes · Peak data volume: 1,000 records per hour · Recommended pattern: Custom service (
RetailTransactionServiceInventory::inventoryLookup) - Import large volumes of sales orders from a front-end system — Real-time data required?: No · Peak data volume: 200,000 records per hour, one time every five minutes · Recommended pattern: Batch data APIs
- Export large volumes of purchase orders to an on-premises inventory system — Real-time data required?: No · Peak data volume: 300,000 records per hour, one time per hour · Recommended pattern: Batch data APIs
Microsoft frames the choice as three questions: whether real time is a business requirement, what the peak data volume is, and what the frequency is. The OData sizing gap deserves its own read.
The constraint that decides each pattern
One documented constraint per surface, each quoted from the Microsoft page named for it in the fact-check block. None of these numbers is ours. The sync/async column is Microsoft's where Microsoft states it — OData, custom service, batch data API — and ours elsewhere.
- OData — Sync or async: Synchronous · The documented constraint, from its own page: "serving driven paging with a maximum page size of 10,000";
$expand"only first-level expansion is supported" - Custom service — Sync or async: Synchronous · The documented constraint, from its own page: Shares service protection limits with OData, which apply "only for finance and operations OData and custom service API endpoints"
- Recurring integrations — Sync or async: Asynchronous · The documented constraint, from its own page: "Until a message is successfully acknowledged, the same message becomes available to dequeue every 30 minutes"
- Data management package REST API — Sync or async: Asynchronous · The documented constraint, from its own page: "Don't call ImportFromPackage() in parallel threads. Otherwise, it fails"
- Business events — Sync or async: Asynchronous push · The documented constraint, from its own page: "the order in which the apps emit the events isn't guaranteed to preserve the order in which they're delivered to the endpoints"
- Data events — Sync or async: Asynchronous push · The documented constraint, from its own page: "a burst rate of 5,000 events per five-minute period, up to 50,000 events per hour, across all entities for the environment" — and "The environment doesn't have limits that explicitly throttle events"
- Virtual entities — Sync or async: Synchronous per query · The documented constraint, from its own page: "always use finance and operations apps and Dataverse that are co-located in the same Azure region… When finance and operations apps and Dataverse are co-located, the virtual entity overhead is expected to be less than 30 milliseconds (ms) per call"
- Dual-write — Sync or async: Synchronous, transactional · The documented constraint, from its own page: "1,000 records" per single transaction writing from finance and operations apps to Dataverse — the reverse direction is bounded by a 116.85 MB payload, not a record count — and "a timeout window of two minutes" on all transactions regardless of record count
- Consume external web services — Sync or async: Caller-defined · The documented constraint, from its own page: The target endpoint "must support TLS 1.2 or later"; the documented mitigation is "introducing a broker service, and making a two-hop call"
- Excel integration — Sync or async: Synchronous · The documented constraint, from its own page: Built on "OData services that are created for publicly exposed data entities"; exempt from service protection API limits
That exemption list is regularly misread, and virtual tables are on it too — but only for the endpoints the virtual entity plugin invokes, and only when the Power Platform integration is enabled.
The same page bounds the virtual-table entry: "the exemption applies only to the Finance and Operations apps API endpoints that the virtual entity plugin invokes… However, because the request is made through the Microsoft Dataverse API, Service protection API limits might still apply." The limit moved meters; it did not disappear.
One documented constraint is a prohibition rather than a number. Microsoft's business events documentation carries an Important callout — "Don't consider business events as a mechanism for exporting data" — because events are meant to be lightweight rather than to carry large payloads.
Which job each pattern is the right answer to
This table is our recommendation, not Microsoft's. Microsoft publishes the scenarios above and stops there; the generalisation is ours.
- OData — Tens to low thousands of records where the caller needs the ERP's answer in the response
- Data management package REST API — A large file-shaped movement on a schedule your orchestrator owns and polls
- Recurring integrations — The same movement, when the schedule belongs inside the ERP and you want files plus XSLT (Extensible Stylesheet Language Transformations)
- Business events — Knowing a business action completed, so something downstream can start
- Data events — Knowing a record changed, where Power Platform integration is already enabled
- Virtual entities — Live, governed read and write from a Power Platform surface, with no copy of the data
- Dual-write — Keeping a small set of overlapping master records identical across the ERP and Dataverse
- Custom service — A coarse-grained operation spanning entities that should not be exposed as row CRUD
- Consume external web services — The ERP initiating a call out to a service you do not control
- Excel integration — A person editing entity data with the validate chain enforced — a human surface, not an application channel
Where we would draw the line
We would not put an optimizer's read path on dual-write. It is the right instrument for what Microsoft describes — near-real-time copying of overlapping entities such as Account/Customer, Company, Product and Sales order — and the wrong one for an analytical read, because it puts an ERP transaction time limit inside your model's data access.
Microsoft on that budget: "The whole time that is spent in Dataverse includes the time that is required to write, and also the time that is required to process the standard and custom plugins." What that costs is its own article.
Virtual entities are also a synchronous call into the ERP — but there is no transaction budget on a read, and the documented overhead is bounded.
How our Optimizers connect. Each Optimizer reads through virtual entities and OData-enabled data entities, subscribes to business events for the trigger, computes the decision on Azure in your tenant, and writes the optimized value — the reorder point, the price, the wave — back through the same published surface, behind a human approval step and inside a named Security Role.
No ERP object is modified.
What to check this week
- Write down which of the ten surfaces in the table above each integration in your estate uses. The one nobody can place is where the review starts.
- Compare each integration's real peak volume against Microsoft's sizing table — as a gauge, in Microsoft's words, not as a limit.
- For every asynchronous integration, find the code that polls for completion. If it does not exist, the integration has no idea whether its work succeeded.
- Ask any vendor which surface it writes through and which Security Role it runs as. Both are inspectable, and a vendor that cannot answer has not designed the write path.
About Cognilium Cognilium builds AI optimization apps for Microsoft Dynamics 365 — companion apps that optimize the pricing, inventory, warehouse and planning decisions your ERP manages but can't optimize. Dynamics is your system of record. Cognilium is your system of intelligence. https://cognilium.ai · https://www.linkedin.com/company/37180269/
If you are choosing the write path for an optimization app and want this table walked against your own estate, book a fifteen-minute call and we will go through it with you live — no deck. https://cognilium.ai
Sources
- Integration between finance and operations apps and third-party services
- Open Data Protocol (OData)
- Custom service development
- Recurring integrations
- Data management package REST API
- Consume external web services
- Office integration overview
- Microsoft Power Platform integration with finance and operations apps
- Virtual entities overview
- Business events overview
- Data events
- Dual-write limits for live synchronization
- Service protection API limits
Sources
- learn.microsoft.com — integration overview
- learn.microsoft.com — odata
- learn.microsoft.com — custom services
- learn.microsoft.com — recurring integrations
- learn.microsoft.com — data management api
- learn.microsoft.com — consume external web service
- learn.microsoft.com — office integration
- learn.microsoft.com — overview
- learn.microsoft.com — virtual entities overview
- learn.microsoft.com — home page
- learn.microsoft.com — data events
- learn.microsoft.com — sync limits
- learn.microsoft.com — service protection api limits
Share this article
Muhammad Mudassir
Founder & CEO, Cognilium AI
Muhammad Mudassir
Founder & CEO, Cognilium AI
Mudassir Marwat's argument is that ERP systems record decisions they never optimise.
