Fabric Orchestration: Dataflow Gen2 vs Pipeline vs Notebook, and Triggers
Orchestration in Microsoft Fabric comes down to three tools with distinct jobs: Dataflow Gen2 is the low-code Power Query surface for connecting to sources and transforming data visually, a data pipeline is the control-flow engine that copies data at scale and coordinates every other workload, and a notebook is the code-first Spark environment for transformations that need real programming. DP-700 tests whether you can choose the right tool for a scenario, wire them together into schedules and event-based triggers (including Activator-driven file-arrival triggers), and pass parameters between pipeline activities and notebooks with dynamic expressions. This lesson gives you the decision table, the trigger options, the parameter-passing mechanics — pipeline parameters, notebook parameter cells, exit values, and expression functions — and the orchestration patterns (parent-child pipelines, metadata-driven ForEach loops, notebook DAGs) that production Fabric solutions are built on.
On this page8 sections
- Choosing between Dataflow Gen2, a pipeline, and a notebook
- Dataflow Gen2: low-code ingestion and transformation
- Data pipelines: control flow and data movement
- Notebooks: code-first Spark transformation
- Schedules and event-based triggers
- Parameters and dynamic expressions in pipelines
- Passing parameters between pipelines and notebooks
- Orchestration patterns and a worked scenario
- Choose between Dataflow Gen2, a data pipeline, and a notebook for a given ingestion or transformation scenario
- Design schedules and event-based triggers, including OneLake and Azure Blob Storage file-arrival events
- Pass values into notebooks with pipeline base parameters and read notebook exit values back into the pipeline
- Build dynamic expressions with pipeline parameters, variables, and activity outputs
- Implement parent-child pipeline patterns and metadata-driven ForEach orchestration
- Chain notebooks efficiently with notebookutils, including DAG-style runMultiple execution
Choosing between Dataflow Gen2, a pipeline, and a notebook
Choose by asking three questions: who builds it, how complex is the transformation, and does it need to coordinate other work? Dataflow Gen2 is for low-code transformation — Power Query Online with a large connector library, built by analysts or engineers who prefer a visual editor, landing results in a Lakehouse, Warehouse, Eventhouse KQL database, or other output destination. A data pipeline is for orchestration and large-scale data movement — the Copy activity plus control-flow activities that schedule, sequence, branch, and retry other workloads; it transforms very little by itself. A notebook is for code-first work — PySpark, Spark SQL, Scala, or R against Lakehouse tables, where transformations are too complex, too dynamic, or too performance-sensitive for a visual tool.
| Dimension | Dataflow Gen2 | Data pipeline | Notebook |
|---|---|---|---|
| Primary persona | Low-code / citizen developer | Data engineer (orchestration) | Pro-code data engineer |
| Interface | Power Query visual editor | Activity canvas (control flow) | Code cells (Spark) |
| Best at | Connector-rich ingestion with visual transforms | Copying data at scale and coordinating workloads | Complex, testable, reusable transformation logic |
| Transformation depth | Moderate (Power Query M) | Minimal (copy with light mapping) | Deep (full Spark programming model) |
| Orchestrates other items | No | Yes — notebooks, dataflows, procedures, other pipelines | Can chain notebooks via notebookutils |
| Parameters and dynamic behavior | Limited | Rich — parameters, variables, expressions | Rich — parameter cell, exit values, code |
| Typical role in a solution | Self-service ingestion and prep | The backbone that schedules everything | The transformation engine pipelines invoke |
The tools compose rather than compete: a common production design is a pipeline that copies raw files into a Lakehouse, invokes a notebook to transform bronze to silver to gold, then refreshes a semantic model — with a Dataflow Gen2 handling a side-channel of business-owned reference data. When an exam scenario stresses "minimal code" or "business analysts," answer Dataflow Gen2; "orchestrate," "schedule," or "copy large volumes," answer pipeline; "complex logic," "custom code," or "Spark," answer notebook.
Dataflow Gen2: low-code ingestion and transformation
Dataflow Gen2 is Power Query running as a Fabric item: you connect to a source, shape the data through applied steps (filter, merge, pivot, custom columns in M), and write the result to an output destination such as a Lakehouse table, a Warehouse table, an Eventhouse KQL database, or an Azure SQL database. Because the editor shows data previews at every step, it is the fastest path for connector-heavy, moderately complex preparation work — and the only one of the three tools a non-programmer can own end to end.
Its orchestration story is deliberately thin: a dataflow can be refreshed on a schedule or invoked from a pipeline with the Dataflow activity, but it cannot itself invoke notebooks, branch on conditions, or loop. That is the boundary the exam probes. A dataflow also supports incremental refresh patterns to avoid reprocessing unchanged data on every run.
Choose Dataflow Gen2 when the source needs one of its many connectors, the transformation fits Power Query comfortably, and the owner prefers visual tooling. Avoid it when transformations demand code-level control or when the task is really orchestration wearing a transformation costume — sequencing steps, conditional retries, and fan-out belong in a pipeline.
Data pipelines: control flow and data movement
A data pipeline is Fabric's orchestrator: a canvas of activities connected by success, failure, completion, and skip dependencies. The Copy activity moves data at scale between a wide range of sources and destinations with light schema mapping. Around it sit invocation activities — Notebook, Dataflow, Stored procedure, Script, Semantic model refresh, Invoke pipeline — and control-flow activities: ForEach (iterate a collection), If Condition and Switch (branch), Until (loop to a condition), Wait, Lookup (fetch rows or config to drive logic), Get Metadata (inspect files and folders), and Set Variable.
Dependency conditions are the error-handling primitive: route the red "on failure" path to a Teams or Outlook activity for alerting, or use "on completion" when a step must run regardless of outcome. Activities also carry retry counts and timeouts, which is why pipelines — not notebooks calling notebooks — are the right home for production reliability requirements.
The pipeline's own transformation vocabulary is intentionally small. If you find yourself contorting Copy activities to reshape data, the design smell is real: land the data, then hand the reshaping to a notebook or dataflow. The pipeline's job is when, in what order, and what happens on failure — not how the bytes are transformed.
Notebooks: code-first Spark transformation
A Fabric notebook runs code on Spark against OneLake data — typically PySpark or Spark SQL reading and writing Lakehouse Delta tables. It is the tool for transformations that need joins across many tables, window functions, data quality rules, machine-learning steps, or any logic you want unit-testable and version-controlled. Notebooks attach to a default Lakehouse, whose tables and files are directly addressable, and can reach other lakehouses through absolute paths or shortcuts.
Notebooks participate in orchestration three ways. First, a pipeline's Notebook activity runs them with parameters — the standard production pattern. Second, notebooks can be scheduled directly from their own settings when a single notebook is the whole job. Third, notebooks can chain each other with notebookutils: notebookutils.notebook.run() executes a child notebook and returns its exit value, and notebookutils.notebook.runMultiple() executes a set of notebooks — optionally as a dependency graph — inside the same Spark session, avoiding the session-startup cost of separate pipeline activities.
That last point is a genuine design trade-off the exam can probe: orchestrating ten small notebooks as ten pipeline Notebook activities gives per-activity monitoring and retries but may pay repeated session overhead; runMultiple inside one driver notebook shares a session and runs a DAG efficiently, at the cost of coarser monitoring. Reach for pipelines when steps are heterogeneous (copy + notebook + procedure) or need individual retry policies; reach for runMultiple when many related Spark steps should share compute.
Schedules and event-based triggers
Fabric starts work two ways: on the clock or on an event. Schedules are configured per item — pipelines, notebooks, and dataflows each have scheduled-run settings where you define frequency (by the minute, hourly, daily, weekly), start and end dates, and time zone. A schedule fires the item regardless of what data has or has not arrived, which makes it the right choice for batch cadences like "load the warehouse nightly" — and the wrong choice when the real requirement is "process each file as it lands."
Event-based triggers answer that second requirement. Fabric's eventing runs through the Real-Time hub and Activator (the evolution of Data Activator/Reflex): a pipeline trigger subscribes to events — OneLake events (files created or modified in a lakehouse) or Azure Blob Storage events (blob created in an external storage account), among other event sources — and starts the pipeline when a matching event arrives. You can filter the subscription (by container, folder path, or file name pattern) so only relevant arrivals fire the trigger, and the event's metadata — such as the arriving file's name and folder path — is exposed to the pipeline as built-in trigger parameters you reference in dynamic expressions, letting one parameterized pipeline process whichever file arrived.
Activator itself generalizes beyond pipeline triggers: it watches streaming data and event sources for conditions (a threshold crossed, a pattern detected) and takes actions such as starting a Fabric job, sending an alert, or calling Power Automate. For DP-700, the essential mapping is: fixed cadence → schedule; react to file or data arrival → event-based trigger via Activator/Real-Time hub; react to conditions in streaming data → Activator rules. Event-driven beats frequent polling schedules both on latency and on wasted runs — the classic exam justification.
Parameters and dynamic expressions in pipelines
Parameters make one pipeline serve many workloads. A pipeline parameter is declared on the pipeline with a type and optional default, is read-only during the run, and is referenced in any activity setting through dynamic content: @pipeline().parameters.SourceFolder. Callers supply values — a manual run prompts for them, a schedule can fix them, an Invoke Pipeline activity maps them, and an event trigger feeds them from event metadata. Variables, by contrast, are mutable during the run: Set Variable writes them, @variables('rowCount') reads them — use variables for state that changes mid-run, parameters for run configuration.
The expression language glues everything together. Expressions start with @ and compose functions: @concat('sales/', pipeline().parameters.Region, '/data.parquet') builds paths; @formatDateTime(utcnow(), 'yyyy/MM/dd') builds date partitions; @activity('LookupConfig').output reads a previous activity's output — the pattern that lets a Lookup activity's result drive a ForEach: set the ForEach items to @activity('LookupConfig').output.value and reference the current element inside the loop with @item() (for example @item().tableName).
System functions like @pipeline().RunId, @pipeline().TriggerTime, and trigger-event metadata round out the vocabulary. The exam pattern to internalize: any answer that hardcodes a file name, date, or table list in ten near-identical pipelines is wrong when a single parameterized pipeline with dynamic expressions can do the job.
Passing parameters between pipelines and notebooks
Values flow into a notebook through the Notebook activity's base parameters. In the notebook, you designate one cell as the parameters cell (toggle it in the cell options) and declare default values there — region = 'emea', load_date = ''. At run time, Fabric injects the base parameters as a new cell that overrides those defaults, so the notebook runs interactively with defaults and runs parameterized under orchestration with no code changes. Match the parameter names and types exactly; a mismatched name silently leaves the default in place.
Values flow back through the notebook's exit value: end the notebook with notebookutils.notebook.exit('42137') and the calling pipeline reads it at @activity('TransformNotebook').output.result.exitValue — feed it to an If Condition to branch on row counts or status codes, or pass it as a base parameter to the next notebook. Exit values are strings, so serialize anything structured (JSON works well) and parse it on the other side.
Session configuration is parameterizable too: the %%configure magic command in a notebook's first cell can set Spark session options and — importantly — the default Lakehouse binding, and it supports parameterization from a pipeline so the same notebook can run against dev and prod lakehouses. Together, base parameters (data in), exit values (results out), and parameterized configuration (environment binding) are the complete notebook-pipeline contract DP-700 expects you to know.
Orchestration patterns and a worked scenario
Three patterns cover most production designs. Parent-child pipelines: a parent pipeline sequences stages and calls child pipelines with the Invoke Pipeline activity, passing parameters down — each child stays small, testable, and independently runnable. Metadata-driven ingestion: a Lookup activity reads a control table listing sources (table name, watermark column, destination), a ForEach iterates it, and inside the loop a parameterized Copy activity and Notebook activity process @item() — onboarding a new source becomes a row insert, not a new pipeline. Notebook DAGs: a driver notebook uses notebookutils.notebook.runMultiple() to run related Spark transformations with dependencies inside one shared session.
Scenario: a retailer's suppliers drop CSV files into an Azure Blob Storage container at unpredictable times; each file must be ingested into a bronze Lakehouse table, transformed to silver with data-quality rules, and the semantic model refreshed — with a Teams alert on any failure. The design: an event-based trigger subscribes to blob-created events on the container, filtered to .csv, and starts one parameterized pipeline, passing the file name and folder path from the trigger's event metadata into pipeline parameters. A Copy activity uses those parameters in dynamic expressions to land exactly that file in the bronze area. A Notebook activity passes the file name as a base parameter; the notebook validates and merges to silver, then exits with the accepted row count via notebookutils.notebook.exit. An If Condition on @activity('Transform').output.result.exitValue routes zero-row loads to a warning path; the success path runs a Semantic model refresh activity; every activity's failure path converges on a Teams activity.
Notice what the scenario did not use: no polling schedule (events beat polling on latency and cost), no logic in the pipeline that belonged in the notebook, and no per-supplier pipeline copies — one parameterized pipeline handles every file. That reasoning, applied under exam time pressure, is the skill this topic measures.
Tip. Expect scenario questions that hand you a persona, a transformation complexity, and a coordination need, and ask you to pick Dataflow Gen2, a pipeline, or a notebook — plus designs that combine them. Trigger questions contrast fixed schedules with event-based triggers for file arrivals (event-driven wins on latency and wasted runs). Parameter mechanics are fair game at the syntax level: @pipeline().parameters.x, @activity('Name').output, @item() inside ForEach, notebook parameters cells, and reading exit values via output.result.exitValue. Know why metadata-driven ForEach patterns beat duplicated pipelines and when runMultiple beats separate Notebook activities.
- Dataflow Gen2 = low-code Power Query transforms with rich connectors; pipeline = control flow, Copy activity, and orchestration; notebook = code-first Spark. They compose: pipelines invoke both.
- Pipelines orchestrate with ForEach, If/Switch, Until, Lookup, Get Metadata, Invoke Pipeline, and dependency conditions (success/failure/completion) that double as error-handling paths.
- Schedules fire on a fixed cadence per item; event-based triggers (Activator/Real-Time hub) fire pipelines on OneLake or Azure Blob Storage file events, passing file name and path as trigger metadata.
- Pipeline parameters are read-only run inputs (@pipeline().parameters.x); variables are mutable run state (@variables('x')); expressions compose functions like concat, utcnow, formatDateTime, and activity outputs.
- Notebooks receive values via base parameters overriding a designated parameters cell, and return results via notebookutils.notebook.exit, read as @activity('Name').output.result.exitValue.
- %%configure lets a pipeline parameterize a notebook's Spark session and default Lakehouse, so one notebook serves dev and prod.
- Metadata-driven orchestration (Lookup + ForEach + parameterized activities) beats copying near-identical pipelines; new sources become control-table rows.
- notebookutils.notebook.runMultiple runs a DAG of notebooks in one shared Spark session — cheaper than many pipeline Notebook activities, at the cost of coarser per-step monitoring and retries.
Frequently asked questions
When should I use a Dataflow Gen2 instead of a notebook in Microsoft Fabric?
Use Dataflow Gen2 when the transformation fits Power Query's visual, step-based model, the source needs one of its many connectors, and the owner prefers low-code tooling — typical for business-owned reference data and moderate-complexity prep. Use a notebook when the logic needs real code: complex joins, window functions, data-quality frameworks, ML steps, or anything you want unit-tested and version-controlled. Cost and scale matter too — heavy transformations on large volumes generally favor Spark notebooks.
How do event-based triggers work in Fabric data pipelines?
A pipeline trigger, powered by Activator through the Real-Time hub, subscribes to events such as OneLake file events or Azure Blob Storage blob-created events. You filter the subscription by container, folder, or file-name pattern, and when a matching event arrives the pipeline starts automatically. The event's metadata — including the file name and folder path — is available as trigger parameters you can map into pipeline parameters, so one pipeline processes whichever file arrived.
How do I pass a value from a pipeline into a notebook and get a result back?
Pass values in through the Notebook activity's base parameters; in the notebook, mark a cell as the parameters cell with matching variable names and defaults — injected values override the defaults at run time. Pass results back by ending the notebook with notebookutils.notebook.exit('value'); the pipeline reads it via @activity('YourNotebook').output.result.exitValue and can branch on it with an If Condition or feed it to the next activity. Exit values are strings, so use JSON for structured results.
What is the difference between pipeline parameters and variables?
Parameters are declared on the pipeline, supplied by the caller (manual run, schedule, trigger, or Invoke Pipeline), and are read-only for the duration of the run — they configure what the run does. Variables are internal, mutable state: you change them mid-run with Set Variable and read them with @variables('name'). If a value comes from outside the run, it is a parameter; if the run computes and updates it, it is a variable.
Should I chain notebooks with a pipeline or with notebookutils.notebook.runMultiple?
Use pipeline Notebook activities when steps are heterogeneous (mixing copy, procedures, and notebooks), need individual retry policies and timeouts, or benefit from per-activity monitoring. Use runMultiple from a driver notebook when many related Spark steps should share one session — it supports dependency-graph execution and avoids paying session startup per step. Many solutions combine both: a pipeline invokes one driver notebook that internally runs a DAG.
Can a Dataflow Gen2 orchestrate other Fabric items?
No. A dataflow transforms data and writes to its output destinations, but it has no control-flow activities and cannot invoke notebooks, pipelines, or other dataflows. Orchestration is the pipeline's job — a pipeline can run a dataflow with the Dataflow activity and sequence it with notebooks, stored procedures, and copies. If a scenario needs branching, looping, or coordination, the answer is a pipeline, never a dataflow.
Sign up free to mark lessons complete, bookmark topics and track your exam readiness.