FetchXML vs OData in Dataverse

Two query languages for Dataverse — what each does, performance and capability differences, and when to choose which.

Updated 2026-12-26

Dataverse exposes its data through two distinct query languages: FetchXML (the older, Dataverse-native XML format) and OData (the standard REST-style query syntax used by most modern API consumers). Both can return the same underlying data; choosing the right one depends on the use case.

FetchXML.

FetchXML is Microsoft's XML-based query language for Dataverse. Used by:

  • Advanced Find in the Dynamics 365 UI — what users see when building filtered views.
  • Views stored in Dataverse — view definitions are FetchXML under the hood.
  • Plug-ins doing complex queries via the SDK.
  • Power Automate Dataverse "List rows" action can use FetchXML for advanced filtering.
  • SSRS reports historically (now Power BI replaces SSRS).

Strengths:

  • Complex queries — group-by, aggregate, hierarchical filtering with nested unions, complex join logic. More expressive than OData for analytical queries.
  • Native to Dataverse — uses Dataverse-specific concepts like Link-Entity, Filter expressions, Order-By.
  • Aggregations — count, sum, avg, min, max within a single query.
  • Distinct — explicit DISTINCT support.

Weaknesses:

  • Verbose XML — substantial markup for non-trivial queries.
  • Dataverse-specific — doesn't translate to other systems.
  • Documentation outside Microsoft's official sites is sparser.
  • Limited 5000-record default page — extends with paging.

OData (Web API).

OData is the standard REST query syntax exposed by Dataverse's Web API (the /api/data/v9.x/ endpoint). Used by:

  • Modern integrations — anything calling Dataverse from external systems.
  • Power Automate flows — most common pattern.
  • Custom JavaScript on forms (Xrm.WebApi).
  • Power BI direct query to Dataverse.
  • Mobile apps and SDKs.

Strengths:

  • Standard syntax$filter, $select, $expand, $orderby, $top, $skip are familiar to anyone with OData experience.
  • Concise — URL-encoded query parameters; no XML.
  • HTTP-native — works directly from REST clients, browsers, Postman.
  • Documented broadly — OData standard documentation plus Dataverse-specific extensions.
  • Modern toolchain — most SDKs and HTTP libraries support it natively.

Weaknesses:

  • Less expressive for complex analytics — aggregations supported but more limited than FetchXML.
  • Some Dataverse-specific operations are awkward in OData (e.g. complex link-entity joins).
  • Filter expression syntax — quite expressive but doesn't support every FetchXML pattern.

Choosing.

Use FetchXML when:

  • You're working with advanced-find or views (the platform uses FetchXML there).
  • The query is highly analytical — group-by, aggregates, complex joins.
  • You're inside a plug-in or other Dataverse SDK context.

Use OData when:

  • Calling Dataverse from an external system.
  • Writing a Power Automate flow's "List rows" action with simple filtering.
  • Writing JavaScript on a form to fetch related records.
  • Building a Power BI direct-query dataset.
  • Anything modern and HTTP-driven.

Conversion. The Dataverse SDK can convert FetchXML to OData and vice versa for many patterns, but not all. Some advanced FetchXML patterns don't translate to OData; some OData patterns don't translate efficiently to FetchXML.

Performance. For equivalent queries, FetchXML and OData both compile to the same underlying SQL. Performance differences are typically negligible. Both honour Dataverse's indexes and security filters identically.

The Dataverse Query Designer. Several community tools (XrmToolBox plug-ins, "FetchXML Builder", "OData Query Designer") let you build queries visually and emit either format. Useful when you know the data but aren't fluent in either syntax.

Mixing approaches in one solution. A non-trivial integration might use both:

  • The flow's main filter is OData (simpler, in Power Automate's Dataverse action).
  • A complex secondary query uses FetchXML (passed to "List rows" with a Fetch XML Query parameter).

Both can be used side by side without conflict.

Common pitfalls.

  • Hand-writing complex FetchXML without the tools — error-prone XML.
  • OData $expand without $select — fetches all expanded fields, blowing up payload size.
  • Filtering on calculated columns — neither query language indexes calculated columns efficiently. Use rollup or stored values.
  • No paging on bulk queries — OData and FetchXML both default to 5000-record pages; explicit paging is required for larger sets.

Operational reality. Most modern Dataverse integration work uses OData. FetchXML remains relevant for analytical work, view-based queries, and SDK-level customisation. Pick deliberately per use case; don't fight the tool.

Related guides