Resources  /  Integration

Why Dynamics 365 F&O integrations double-post, and how to make them exactly-once


Every integration retries sooner or later. When the call it retries posts a journal or invoices an order, the retry is how duplicates reach the ledger. Here's how to make retries harmless.

Retries are not an edge case

Networks drop, gateways time out, and message brokers redeliver by design. A caller that does not hear back cannot know whether its request failed or succeeded silently, so it sends it again. For a read, that costs nothing. For a call that posts a journal, invoices a sales order or settles a payment, it is how the same document reaches the ledger twice, and the duplicate is usually found at month end by someone reconciling a balance that will not tie.

Why duplicate checks in the caller fall short

The usual fix is to make the calling system remember what it sent and check before sending again. That moves the problem rather than solving it: the caller still cannot see whether a call that timed out actually posted, every integration has to rebuild the same logic, and each one gets it slightly differently wrong. The only place that knows for certain whether a document was created is the ERP, inside the transaction that created it.

Make the ERP answer the retry

An exactly-once service takes a request id from the caller and records a claim on it in the same transaction as the document it creates. A repeat of that id returns the original result instead of posting again, whether the first call finished a second ago or crashed halfway. A scheduled sweep finds any claim a crash left in progress and resolves it: finalized if the document posted, released if it never existed, or parked for a person to look at. Add a dry-run preview that validates a request without posting or consuming a number, and integrators can test against production rules without touching the books.

Recovery has to be exactly-once too

Failures still happen, and the fix matters as much as the guarantee. When a failed message is retried from a dead-letter queue, it should reuse its original request id, so a message that half-succeeded the first time cannot post again on the second. That combination (idempotent services, a reconciliation sweep, previews and replayable recovery) is how Lattice's integration operations work across every one of its posting services, so your integrators get the guarantee without building it.


Related product

Lattice. One integration foundation for Dynamics 365: data, operations, and events in a single surface.

An unhandled error has occurred. Reload 🗙

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.