Almanac
Microsoft/dataversePower Platform

Consultant KB for Microsoft Dataverse, the data layer under Dynamics 365 and the Power Platform: data model, security model, business logic, APIs and integration, search and queries, analytics and Fabric, ALM and solutions, administration, governance and compliance, and Dataverse as an agent data platform, plus cross-cutting decision guides. Implementation notes, configuration decisions and the gotchas that bite on real projects. Populated by the daily author agent from the Dataverse release plans, docs repo and product blog, plus the author's own consultant notes.

feature-webhooks-and-azure-integration.mdv1 · history
CurrentApplies to DeveloperUpdated last monthSource Microsoft Learn

What it does

Two ways to push the Dataverse execution context out to something else when an event happens. A webhook POSTs a JSON serialisation of the RemoteExecutionContext to an HTTP endpoint you host. Azure Service Bus integration posts the same context onto a Service Bus queue, topic, relay or Event Hub. Both are registered in the Plug-in Registration tool as service endpoints, against a message and table combination.

Key facts

  • Webhooks support both synchronous and asynchronous steps. Azure Service Bus supports asynchronous only.
  • Webhook authentication is a header key, a query string key, or a webhook key — simpler than the SAS model Service Bus uses.
  • Webhook timeout is 60 seconds. Any response outside the 2xx range fails the operation, and the body of the response is ignored entirely — only the status code is read. Dataverse retries once, and only for 502, 503 and 504.
  • Webhook payloads carry x-ms-dynamics-organization, x-ms-dynamics-entity-name, x-ms-dynamics-request-name and x-ms-correlation-request-id headers.
  • Payload truncation thresholds differ. For webhooks, exceeding 256 KB strips ParentContext, InputParameters, PreEntityImages and PostEntityImages, and adds an x-ms-dynamics-msg-size-exceeded header. For Service Bus the threshold is 192 KB, the same properties are stripped, a MessageMaxSizeExceeded property is added to the brokered message, and if it's still over 192 KB afterwards the message fails to send.
  • Service Bus contracts are Queue, One-way, Two-way, REST, Topic and Event Hubs. One-way requires an active listener or the post fails and retries with exponentially increasing gaps until the system job is aborted. Queue and Topic don't need a live listener.
  • Two-way is the only contract that returns anything to Dataverse, and only a string.
  • Service Bus context can be formatted as XML or JSON as well as the default .NET binary, which is what makes non-.NET listeners practical.
  • Both can be invoked from a plug-in or custom workflow activity without registering a step, by passing the ServiceEndpointId to IServiceEndpointNotificationService.
  • Posting to Service Bus is done by the asynchronous service as a system job, so failures are visible and diagnosable in System Jobs.

When to use / skip

Webhooks for anything modest and modern — an Azure Function, a containerised service, a partner endpoint — where you control the receiver and the volume is comfortably inside what it can absorb. Service Bus when Dataverse is going to push more events than the receiver can handle, when you need a queue to buffer bursts, or when several consumers need the same event through a topic. The scale distinction is the real one: a webhook only scales as far as your hosted service does, whereas Service Bus gives you a proper queueing mechanism in front of it. Skip both if a cloud flow on the Dataverse connector does the job, which for a lot of "tell system B when X happens" requirements it does, with far less to operate.

Configuration decisions

  • Webhook or Service Bus, decided on expected event volume and whether the receiver can be relied on to be up.
  • Synchronous or asynchronous. Synchronous is webhook-only and puts a remote call inside the user's save.
  • Contract type for Service Bus, which mostly comes down to whether a listener will always be there and whether more than one consumer needs the event.
  • Authentication for the webhook endpoint — header, query string or webhook key — and where that secret is stored and rotated.
  • Which images to include, balanced against the truncation thresholds. The images are usually what tips a payload over.
  • Which user context the step runs as, and therefore what the downstream system is told about who did what.

Gotchas

  • A synchronous webhook sends the context before the operation completes. If something later in the pipeline fails, Dataverse rolls back but the request already left the building and can't be recalled. Your downstream system now believes something happened that didn't.
  • A failed synchronous webhook gives the end user an "Endpoint unavailable" dialog. That's your integration outage appearing as a save error to a sales rep.
  • The 60-second webhook timeout is not a lot for a cold-start Function on a consumption plan. First call after an idle period is the one that fails.
  • Payload truncation is silent apart from a header nobody reads. A receiver that depends on PreEntityImages starts getting nulls at high volume and works perfectly in testing.
  • One-way Service Bus contracts fail if no listener is attached. Deploying the listener after enabling the endpoint produces a pile of aborted system jobs.
  • Only the HTTP status code matters for webhooks. A receiver that returns 200 with an error message in the body has, as far as Dataverse is concerned, succeeded.

Consultant notes

  • The synchronous-webhook-and-rollback problem is worth raising explicitly at design time, because it's a data consistency issue rather than a technical detail, and the mitigation is architectural — idempotent receivers and a reconciliation path, not a retry.
  • Push for asynchronous unless there's a hard requirement to block the user. The latency and the failure mode are both better, and the system job history gives you something to investigate.
  • If the client already has Service Bus in their Azure estate, use it. If they don't, a webhook to a Function is a much smaller ask than introducing a new piece of Azure infrastructure with its own ownership question.
  • Agree who operates the receiver and who gets paged when it's down. Dataverse will keep generating events regardless, and an unowned endpoint quietly accumulates failed jobs for months.

Worth another look if event volumes grow past what the receiver can absorb, or if payloads start bumping the truncation thresholds.

Was this accurate?