FetchXML vs OData in Dataverse
By Emil Björk · Microsoft business apps consultant, Gothenburg
Two query languages for Dataverse — what each does, performance and capability differences, and when to choose which.
On this page (5)
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,$skipare 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.
Frequently asked questions
When should I use FetchXML instead of OData?
- For analytical queries with group-by, aggregates, distinct, and complex link-entity joins, inside plug-ins or SDK code, and wherever the platform already uses it — views and Advanced Find are FetchXML underneath.
Which is faster, FetchXML or OData?
- Neither in practice. Both compile to the same underlying SQL, honour the same indexes and security filters, and perform equivalently for equivalent queries.
Can I use FetchXML in Power Automate?
- Yes. The Dataverse List rows action accepts a Fetch XML Query parameter for advanced filtering, and it can sit alongside OData filters in the same flow.
What are the common query mistakes?
- Using $expand without $select and pulling every related column, filtering on calculated columns that neither language indexes well, hand-writing complex FetchXML without a builder tool, and forgetting that both default to 5,000-row pages.
Related guides
- Dataverse row-level security for Entra ID B2B guest usersHow to give partners, contractors, and customers direct Dynamics 365 access as Entra B2B guests without exposing more than their own rows — licensing.
- Azure API Management in front of DataverseHow API Management acts as a façade for Dynamics 365 APIs — rate limiting, authentication, transformation, observability, and developer portal.
- Batch operations in the Dataverse Web APIHow to make multiple Dataverse Web API calls in one HTTP round-trip — $batch requests, change sets, and the performance gains at scale.
- Microsoft Graph and DataverseHow Microsoft Graph connects Microsoft 365 data to Dynamics 365 — Graph connectors, indexing Dataverse content, and the Copilot enablement story.
- Power Automate connectors for Dynamics 365The standard and premium Power Automate connectors for Dynamics 365 — what each one does, the differences, and the licensing implications.
Browse every guide in Integrations or just API & identity.
Was this helpful?
Signals which guides land and which need work. No account, no comment box — corrections go through the contact page.
Spot something wrong or want a topic covered? Send a correction or a topic request — both are welcome.