What it does
Power Query running in the cloud, pulling from a source, transforming, and writing rows into Dataverse tables on a refresh schedule. Standard dataflows are the usual way to get data into Dataverse without writing an integration.
Key facts
- Whether a refresh creates or upserts is decided entirely by whether you select a key column. Pick a key and it upserts; leave it blank and every refresh creates new rows.
- The key you set is the Alternate Key in field mapping, not the primary name field. The primary name is a display label, can hold duplicates, and is not a uniqueness constraint no matter what it looks like in the UI.
- A key can be a source system's own identifier, a concatenated column you build in Power Query, or a combination of columns — a composite key.
- Dataverse rows have GUID primary keys that dataflows can't set by default. When loading to an existing table you can select the table's unique identifier (always named
tablename+id) as the key and map a source column to it. The field only accepts strings containing GUID values; anything else fails the create. - Delete rows that no longer exist in the query output keeps the table in step with the source, at the cost of a row-by-row comparison on every refresh. Standard V2 dataflows need
createdonandmodifiedonon the destination table for this to work at all — without those columns, nothing is deleted. - Mapping to polymorphic lookups isn't supported. Neither is mapping to a lookup that points at another table's lookup.
- Mapping to Status and Status Reason isn't supported.
- Line breaks in multi-line text are stripped. Use a
<br>tag if you need them preserved. - You can't map to a column whose
IsValidForCreateproperty is false — the Account field on Contact is the documented example. - Configuring a single-select and a multi-select choice on the same table, with more than one value on the multi-select, isn't supported.
When to use / skip
Dataflows are the right tool for reference data and for periodic loads from a source nobody wants to build a proper integration against — supplier lists, product catalogues, an extract from a finance system. They're the wrong tool for anything near real time, anything transactional, and anything where a partial failure needs to be handled precisely. The moment someone says "and it needs to be within five minutes", stop and reach for a proper integration pattern. The other honest limit: dataflows are excellent at getting data in and poor at telling you what happened, so if audit matters, budget for the monitoring separately.
Configuration decisions
- Whether this load upserts or appends, which is the key column decision and the single most consequential thing on the page.
- What the key actually is — a natural key from the source, a concatenation, or a composite. Get this wrong and you either duplicate or you merge rows that shouldn't merge.
- Whether to take control of the Dataverse GUID by mapping the unique identifier column, which is powerful for keeping identifiers aligned with an external system and unforgiving if the source produces anything that isn't a GUID.
- Whether the destination should mirror the source exactly, and so whether to accept the refresh cost of deleting rows that no longer exist.
- Refresh frequency, weighed against how long a full comparison takes on a table of that size.
Gotchas
- The primary name field looks like the identity field to anyone who hasn't done this before, and mapping the key to it produces silent duplicates on the second refresh.
- Delete-rows-that-no-longer-exist quietly does nothing if
createdonandmodifiedonaren't on the destination table. No error, just rows that never go away. - Line breaks disappearing from multi-line text is the kind of thing users find weeks later in a notes field.
- The unsupported mappings — polymorphic lookups, multi-level lookups, status and status reason — are exactly the columns a business user will ask you to populate first.
- Turning a create-only dataflow into an upsert after it's been running is not a config change, it's a data cleanup exercise.
Consultant notes
- Nail the key column in design and write it into the mapping document. It's the one decision that costs a day to change later and a week to change after go-live.
- Push status and status reason out of the dataflow and into a downstream flow or plug-in. Trying to force them through mapping burns time for nothing.
- Warn clients that dataflow refresh isn't transactional in the way they imagine. Build the monitoring report rather than assuming someone will notice a failed refresh.
- For anything at real volume, compare against the Fabric and Synapse paths before committing. Dataflows are convenient, not fast, and convenience stops being the deciding factor around the point where refreshes start overlapping.
Worth revisiting if polymorphic lookup mapping ever becomes supported, or if the Standard V2 delete behaviour changes.