What this means for your store
Dataflows are the heavy lift: wide Salesforce extracts, multi-object joins, nightly loads. Recipes sit on top - drag-and-drop filters, renames, and roll-ups that sales ops can tweak without touching JSON node graphs. Pick wrong and you get 45-minute refreshes or a dataset nobody can extend when Q4 adds a custom DealerTier__c field.
Scenario on a real storefront
A US industrial distributor tracks open pipeline at opportunity grain but needs order-line revenue from fulfilled B2B carts. Heavy join in the dataflow; rep-friendly KPIs in a recipe:
# Dataflow - extract + join at load time
sfdcDigest Opportunity as opp
sfdcDigest Order as ord
sfdcDigest OrderItem as oi
augment opp_oi = opp, oi, opp.Id == oi.OrderId
@source = 'leftouter'
# Recipe (UI) - built on opp_oi dataset
Filter: StageName != 'Closed Lost'
Compute: DaysInStage = date_diff('day', LastStageChangeDate, now())
Aggregate: PipelineByRep = sum(Amount) group by OwnerId, FiscalQuarter
# Data Manager → Monitor: dataflow finished before recipe run
What to do next
- Keep joins and grain in the dataflow - recipes are bad at custom SAQL nodes, external CSV inputs, and six-object fan-out.
- Three recipes stacked on each other is a maintenance trap; each layer adds refresh minutes and makes it harder to explain why Tuesday's pipeline moved.
- Write the row grain in the dataflow header comment before anyone builds a lens - one row per opportunity vs per order line.
Bottom line
Dataflows own ETL and joins; recipes speed up sales-facing transforms on top. Start with dataflow for grain, layer recipes for filters and KPIs reps actually open.