Dynamics 365 Dual-write: F&O to Dataverse Bidirectional Sync

Type: ERP Integration System: Microsoft Dynamics 365 F&O (10.0.x) Confidence: 0.93 Sources: 8 Verified: 2026-03-02 Freshness: 2026-03-02

TL;DR

System Profile

Dual-write is a Microsoft-provided infrastructure that enables near-real-time, bidirectional data synchronization between Dynamics 365 Finance & Operations (F&O) apps and customer engagement (CE) apps built on Microsoft Dataverse. It ships as two Marketplace solutions installed on Dataverse that extend the table schema, plugins, and workflows to handle ERP-scale data volumes. Covers all F&O SKUs (Finance, Supply Chain Management, Commerce, Project Operations). Does NOT cover Business Central integrations.

PropertyValue
VendorMicrosoft
SystemDynamics 365 Finance & Operations (10.0.x, continuous updates)
API SurfaceDual-write (bidirectional OData-based sync framework)
Current VersionContinuously updated via Marketplace solutions
Editions CoveredFinance, Supply Chain Management, Commerce, Project Operations
DeploymentCloud (required)
API DocsDual-write documentation
StatusGA (Generally Available)

API Surfaces & Capabilities

Dual-write is a synchronization framework, not a traditional API. It uses table-to-table maps defining how data flows between F&O data entities and Dataverse tables, handling OData and plugin orchestration automatically.

CapabilityProtocolBest ForMax Records/RequestTimeoutReal-time?Bidirectional?
Live Sync (F&O to Dataverse)OData/PluginsIndividual record CRUD, master data1,000 records/transaction2 minYesYes
Live Sync (Dataverse to F&O)OData/PluginsIndividual record CRUD, master data116.85 MB payload/transaction2 minYesYes
Initial Sync (F&O to Dataverse)Batch exportBulk data load, go-live migration500,000 rows/run/legal entity5 min (export)NoConfigurable
Initial Sync (Dataverse to F&O)Batch importBulk data load, go-live migration500,000 rows/run/legal entity24 hoursNoConfigurable
Catchup SyncQueue-basedRecovery after pause/maintenanceQueue-based (no explicit limit)1 day retentionNoYes

Rate Limits & Quotas

Per-Transaction Limits (Live Sync)

Limit TypeValueDirectionNotes
Max records per transaction1,000F&O to DataverseSplit transactions with >1,000 records into batches of 1,000
Max payload per transaction116.85 MBDataverse to F&OError code -2147220970 if exceeded
Transaction timeout2 minutesBoth directionsAll transactions exceeding 2 min are rolled back on both sides
Legal entities (live sync)250BothLimit during live synchronization
Legal entities (environment linking)40Setup phaseError if >40 legal entities during initial linking
Concurrent requestsGoverned by Dataverse service protection limitsF&O to DataversePer-tenant daily API call limits apply

Initial Sync Limits

Limit TypeValueDirectionNotes
Max rows per run500,000BothPer legal entity; each legal entity runs separately
Single-threaded table max rows70,000Dataverse to F&OTimeout if exceeded; migrate data separately instead
F&O data export timeout5 minutesF&O to DataverseOptimize queries, add missing indexes, check virtual columns
F&O import result timeout24 hoursDataverse to F&OFor very large datasets, migrate independently
Max lookups per table map10Dataverse initial syncSplit lookups into batches if >10
Visible errors in error log5BothOnly top 5 errors shown per initial sync run

Authentication

Dual-write does not require separate OAuth or API key authentication. The integration is established by linking F&O and Dataverse environments through the Power Platform integration process.

Setup MethodUse WhenConfigurationNotes
Power Platform Integration (LCS)New F&O deploymentsLink via LCS environment setupRecommended for new implementations
Power Platform Admin CenterExisting environmentsConnect existing F&O to existing DataverseRequires Global Admin or Dynamics 365 Admin role
Dual-write Connection SetupAfter environment linkingConfigure in F&O Dual-write admin workspaceOnly the linking user can create initial maps

Authentication Gotchas

Constraints

Integration Pattern Decision Tree

START -- User needs to sync data between F&O and Dataverse/CE apps
|-- Is the data master data (customers, vendors, products)?
|   |-- YES --> Dual-write with pre-built table maps
|   |-- NO --> Is it transactional data (orders, invoices)?
|       |-- YES --> Dual-write (prospect-to-cash, procure-to-pay)
|       |-- NO --> Consider Data Management Framework or custom integration
|-- What's the data volume per transaction?
|   |-- < 1,000 records --> Standard Dual-write live sync
|   |-- 1,000-500,000 records --> Split into transactions of 1,000 records each
|   |-- > 500,000 records --> Migrate independently, skip initial sync
|-- Do you need bidirectional sync?
|   |-- YES --> Dual-write (design conflict resolution via "Master" setting)
|   |-- NO, read-only from F&O --> Consider Virtual Entities (no data duplication)
|-- Is the F&O environment cloud-hosted?
|   |-- YES --> Dual-write supported
|   |-- NO (on-premise) --> Dual-write NOT supported; use OData or custom integration
|-- Encountering timeouts?
|   |-- Transaction timeout (2 min) --> Optimize Dataverse plugins, reduce mapped fields
|   |-- Initial sync timeout --> Check data volume against limits

Quick Reference: Pre-built Table Maps

CategoryExample MapsF&O EntityDataverse TableThreadingNotes
Customer MasterCustomers V3CustCustomerV3EntityaccountSingleMax 70K rows from Dataverse
Vendor MasterVendors V2VendVendorV2Entitymsdyn_vendorSingleMax 70K rows from Dataverse
Product MasterReleased products V2EcoResReleasedProductV2Entitymsdyn_sharedproductdetailMultiUp to 500K rows
SalesSales order headers/linesSalesOrderHeaderV2EntitysalesorderMultiProspect-to-cash
InventoryOn-hand inventoryInventOnHandEntitymsdyn_inventoryonhandMultiNear-real-time availability
ProjectProject contracts/tasksProjProjectEntitymsdyn_projectMultiProject Operations
FinanceLedger/CurrenciesLedgerEntitymsdyn_ledgerMultiPrerequisite for all maps
OrganizationLegal entitiesCompanyInfoEntitycdm_companyMultiMust be synced first

Step-by-Step Integration Guide

1. Link F&O and Dataverse environments

Establish the Power Platform integration by connecting your F&O environment to a Dataverse instance via LCS or Power Platform Admin Center. [src1]

Via LCS:
1. Open LCS > Environment details for your F&O environment
2. Click "Power Platform Integration" > "Setup"
3. Select existing Dataverse environment or create new one
4. Confirm linking

Verify: In F&O, navigate to System Administration > Setup > Dual-write -- the admin workspace should appear.

2. Install Dual-write Marketplace solutions

Install the two required solutions on your Dataverse environment from the Dynamics 365 admin center. [src1]

Via Power Platform Admin Center:
1. Navigate to admin.powerplatform.microsoft.com
2. Select your Dataverse environment
3. Go to Resources > Dynamics 365 apps
4. Install "Dual-write core solution" and "Dual-write application solution"
5. Wait 10-30 minutes for installation

Verify: Open Dual-write admin workspace in F&O -- table maps should populate.

3. Configure and run initial synchronization

Run initial sync following the dependency order: Company > Currency > Customers > Vendors > Products > Transactional data. [src3]

Recommended order:
1. Company and currencies (prerequisites)
2. Chart of accounts and financial dimensions
3. Customers V3 (single-threaded: <70K rows from Dataverse)
4. Vendors V2 (single-threaded: <70K rows from Dataverse)
5. Products (multi-threaded: up to 500K rows)
6. Sales orders and lines
7. Remaining maps

For tables >500K rows: migrate independently + skip initial sync

Verify: Check Initial sync details tab -- status should show Completed.

4. Configure alert notifications for production

Set up error thresholds to automatically pause Dual-write during outages. [src4]

In Dual-write admin workspace:
1. Select table map to monitor
2. Click "Create alert settings"
3. Configure: 10 Application errors in 15 minutes > Pause + email
4. Restart table map for alerts to take effect

Verify: Trigger a test error and confirm notification delivery + automatic pause.

Code Examples

X++: Split large transactions into Dual-write-safe batches

// Input:  Collection of records to create in F&O (syncs to Dataverse)
// Output: All records created in batches of 1,000 within 2-min timeout

int batchCounter = 0;
boolean commitPending = false;

while select myRecordBuffer
    where myRecordBuffer.Status == MyStatus::Pending
{
    if (batchCounter == 0)
    {
        ttsbegin;
        commitPending = true;
    }

    myRecordBuffer.insert(); // Triggers Dual-write sync

    batchCounter++;

    if (batchCounter >= 1000)
    {
        ttscommit;
        commitPending = false;
        batchCounter = 0;
    }
}

if (commitPending)
{
    ttscommit; // Commit remaining records
}

PowerShell: Monitor Dual-write map status

# Input:  Dataverse environment URL + access token
# Output: List of Dual-write table maps and status

$envUrl = "https://yourorg.crm.dynamics.com"
$token = "Bearer <your-access-token>"

$response = Invoke-RestMethod `
  -Uri "$envUrl/api/data/v9.2/dualwriteentitymaps" `
  -Headers @{ "Authorization" = $token; "Accept" = "application/json" } `
  -Method Get

$response.value | ForEach-Object {
    [PSCustomObject]@{
        Name       = $_.msdyn_name
        Status     = $_.msdyn_status
        LastSync   = $_.msdyn_lastsynctime
        ErrorCount = $_.msdyn_errorcount
    }
} | Format-Table -AutoSize

Data Mapping

Table Map Architecture

F&O EntityDataverse TableDirectionKey FieldsThreading
CustCustomerV3Entityaccount (Customers V3)BidirectionalCustomerAccountSingle-threaded
VendVendorV2Entitymsdyn_vendor (Vendors V2)BidirectionalVendorAccountNumberSingle-threaded
EcoResReleasedProductV2Entitymsdyn_sharedproductdetailBidirectionalProductNumberMulti-threaded
SalesOrderHeaderV2EntitysalesorderBidirectionalSalesOrderNumberMulti-threaded
CompanyInfoEntitycdm_companyBidirectionalDataAreaIdPrerequisite
CurrencyEntitytransactioncurrencyF&O to DataverseCurrencyCodePrerequisite

Data Type Gotchas

Error Handling & Failure Points

Common Error Codes

CodeMeaningCauseResolution
DIPV1000Connection validation failedPower Apps ApiHub connections expiredRe-create connection sets
DIPV1002Cross-company data sharing conflictCross-company sharing enabled on F&O entityDisable cross-company sharing or use different entity
DIPV1003Integration keys missingNo alternate key on Dataverse tableDefine alternate key in Power Apps maker portal
DIPV1010Mandatory field unmappedRequired field not mapped in table mapMap all mandatory fields or add default transforms
DIPV1019Missing versionnumber fieldUnsupported table type (virtual/elastic)Use standard table with versionnumber field
-2147220970Message size exceededPayload >116.85 MB from DataverseSplit transaction into smaller batches
MalformedLineExceptionDouble quote parsing failureDouble quotes in source dataRemove double quotes before syncing

Failure Points in Production

Anti-Patterns

Wrong: Running Dual-write maps during bulk data migration

// BAD -- Each migrated record triggers individual sync, destroying performance
1. Enable Dual-write map for Customers V3
2. Start DMF import of 200,000 customers
3. Each insert triggers sync -- 200K individual operations
4. Result: hours instead of minutes; possible timeouts

Correct: Complete migration first, then enable Dual-write

// GOOD -- Migrate independently, then enable live sync
1. Import 200,000 customers into F&O via DMF
2. Import matching 200,000 accounts into Dataverse
3. Enable Dual-write maps with "Skip initial sync"
4. Result: migration in minutes; Dual-write handles only new changes

Wrong: Creating >1,000 records in a single X++ transaction

// BAD -- Exceeds Dual-write 1,000-record limit
ttsbegin;
while select forUpdate myRecord where myRecord.Status == Status::New
{
    myRecord.Status = Status::Active;
    myRecord.update(); // All 5,000 updates in ONE transaction
}
ttscommit; // FAILS: Dual-write rejects >1,000 records

Correct: Batch records into groups of 1,000

// GOOD -- Split into safe batches
int counter = 0;
ttsbegin;
while select forUpdate myRecord where myRecord.Status == Status::New
{
    myRecord.Status = Status::Active;
    myRecord.update();
    counter++;
    if (counter >= 1000) { ttscommit; ttsbegin; counter = 0; }
}
ttscommit;

Wrong: Running Contact initial sync while Customer map is active

// BAD -- Shared address tables cause lock contention
1. Customer V3 map: Running (live sync active)
2. Start initial sync for Contacts
3. Result: performance degradation, address table locks, errors

Correct: Pause Customer map during Contact initial sync

// GOOD -- Stop conflicting maps first
1. Pause Customer V3 map
2. Run Contact initial sync to completion
3. Resume Customer V3 map (catchup handles queued changes)

Common Pitfalls

Diagnostic Commands

# Check Dual-write map status in F&O
# Navigate: System Administration > Setup > Dual-write > Table maps

# Check initial sync progress
# Dual-write admin workspace: select map > "Initial sync details" tab

# View catch-up errors after resume
# Dual-write admin workspace: select map > "Catch-up errors" tab

# Check Dataverse API limits usage
# Power Platform Admin Center > Environments > Analytics > API calls

# Test environment connectivity
# Dual-write admin workspace: "Test connection" button

# View activity log for a table map
# Dual-write admin workspace: select map > "Activity log" tab

# Download detailed error logs
# Activity log: click event > "Download logs"

Version History & Compatibility

ReleaseDateStatusKey ChangesNotes
Continuous updates (2026)OngoingCurrentMCP server for Dataverse (GA)Per-update release cadence
2024 Wave 22024-10SupportedLegal entity limit: 40 to 250 (live sync)Major scalability improvement
2021 Wave 12021-04SupportedCatchup write management; alert notificationsFirst error queue UI
PU37+2020-11Minimum required5-min export timeout handlingRequired for reliable initial sync
Original GA2019LegacyInitial Dual-write releaseNo longer recommended

When to Use / When Not to Use

Use WhenDon't Use WhenUse Instead
Bidirectional near-real-time master data sync between F&O and CE appsRead-only access to F&O data (no duplication needed)Virtual Entities
Pre-built scenarios: prospect-to-cash, procure-to-pay, project-to-cashBulk migration >500K rows per legal entityData Management Framework
No-code/low-code integration between Microsoft D365 appsIntegration with non-Microsoft systems (SAP, Salesforce)OData API or Azure Integration Services
Cloud-hosted F&O environmentOn-premise F&O deploymentOData endpoints or custom API
Transaction volumes <1,000 records per operationHigh-frequency, >1,000 records/secondBatch processing or event-driven architecture

Cross-System Comparison

CapabilityDual-writeVirtual EntitiesDMFOData API
Data DirectionBidirectionalRead-only from F&OImport/ExportFull CRUD
Data StorageCopied to both systemsData stays in F&O onlyStaging tablesPer-request
LatencyNear-real-time (<1s)Real-time (query-time)Batch (min to hrs)Real-time
Max Records/Op1,000/transactionNo limit (query-based)Millions (file-based)Standard OData limits
Storage CostDouble (data in both)NoneStaging onlyNone
Setup ComplexityLow (pre-built maps)Low (configuration)Medium (packages)High (custom dev)
Offline SupportYes (catchup on resume)NoYes (file-based)No
Custom Table SupportYes (extensible)Yes (configurable)YesYes
Best Use CaseMaster data syncReporting, lookupsBulk migration, ETLCustom integrations

Important Caveats

Related Units