Azure Data Factory Overview
Azure Data Factory is Microsoft’s managed ETL and data orchestration service. Think of it as the plumbing between your data sources and your analytics destinations — it connects to databases, SaaS applications, file systems, and cloud services on both sides, then moves, copies, and transforms data on a schedule or in response to events. Whether you need to pull records from an on-premises SQL Server into a data lake every hour or orchestrate a complex multi-step ML training pipeline, ADF is the tool that ties the pieces together.
Core concepts
ADF has a set of building blocks. Understanding them before you build a pipeline saves a lot of confusion:
| Concept | What it is | Analogy |
|---|---|---|
| Linked Service | A connection definition — credentials and endpoint for a data source or destination | A saved database connection string |
| Dataset | A named reference to data within a linked service — e.g., a specific table, folder, or file | A pointer to a specific table in a database |
| Activity | A single step in a pipeline — Copy, Data Flow, Stored Procedure, Notebook, etc. | One step in a workflow |
| Pipeline | A logical grouping of activities with dependencies between them | A workflow or job definition |
| Trigger | What causes a pipeline to run — schedule, tumbling window, storage event, or manual | A cron job or event hook |
| Integration Runtime | The compute infrastructure that executes pipeline activities | A worker server (Azure-managed or self-hosted) |
The most important activity types
ADF has over 30 built-in activity types. Here are the ones you will use most often:
Copy Activity — the workhorse. Moves data from source to sink (destination). Can handle column renaming, type conversion, and schema drift. Parallelises automatically using multiple Data Integration Units (DIUs). Supports incremental copy with watermark or last-modified-time filtering.
Mapping Data Flow — a code-free, visually-designed transformation canvas. You drag and drop transformations (join, aggregate, filter, pivot, window function, etc.) and ADF compiles them into Spark code that runs on a managed cluster. No Spark knowledge needed, but the generated code is Spark under the hood.
Notebook Activity — runs a Databricks notebook or Synapse Spark notebook as a pipeline step. Use this when your transformation logic is already written in Python/PySpark and you want to invoke it from a scheduled pipeline.
Stored Procedure Activity — calls a stored procedure on Azure SQL Database, Synapse dedicated pool, or SQL Server. Useful for post-load merge logic or refreshing materialised views.
Lookup Activity — reads a single value or row from a source. Commonly used to read a watermark timestamp from a control table before an incremental load.
ForEach Activity — iterates over an array and runs child activities for each item. Use it to process multiple files or tables in a loop without duplicating pipeline logic.
A real pipeline: incremental load with watermark
The incremental load pattern is the most common ADF use case. You maintain a watermark (a timestamp of the last successful load) and extract only records modified since that timestamp. Here is how it works in practice:
// Pipeline JSON (simplified) for incremental SQL → ADLS load
{
"name": "IncrementalOrderLoad",
"activities": [
{
"name": "GetWatermark",
"type": "Lookup",
"typeProperties": {
"source": {
"type": "AzureSqlSource",
"sqlReaderQuery": "SELECT MAX(last_load_time) AS watermark FROM dbo.pipeline_control WHERE pipeline_name = 'OrderLoad'"
},
"dataset": { "referenceName": "ControlDB" }
}
},
{
"name": "CopyIncrementalOrders",
"type": "Copy",
"dependsOn": [{ "activity": "GetWatermark", "dependencyConditions": ["Succeeded"] }],
"typeProperties": {
"source": {
"type": "AzureSqlSource",
"sqlReaderQuery": {
"value": "SELECT * FROM dbo.Orders WHERE modified_date > '@{activity('GetWatermark').output.firstRow.watermark}'",
"type": "Expression"
}
},
"sink": {
"type": "ParquetSink",
"storeSettings": {
"type": "AzureBlobFSWriteSettings",
"copyBehavior": "PreserveHierarchy"
}
}
}
},
{
"name": "UpdateWatermark",
"type": "SqlServerStoredProcedure",
"dependsOn": [{ "activity": "CopyIncrementalOrders", "dependencyConditions": ["Succeeded"] }],
"typeProperties": {
"storedProcedureName": "dbo.UpdateWatermark",
"storedProcedureParameters": {
"pipeline_name": { "value": "OrderLoad" },
"new_watermark": { "value": "@{utcNow()}" }
}
}
}
]
}This pipeline reads the last watermark, copies only new/changed orders since that timestamp to ADLS as Parquet, then updates the watermark for the next run. It is resilient — if the copy fails, the watermark is not updated, so the next run re-attempts the same data range.
Integration Runtime: Azure-managed vs self-hosted
The Integration Runtime (IR) is the compute that executes your pipeline activities. There are three types:
Azure Integration Runtime — fully managed by Microsoft. No configuration needed. Can run Copy Activities and Data Flows within Azure. Cannot connect to on-premises or private network resources.
Self-Hosted Integration Runtime (SHIR) — software you install on a Windows server in your network (on-premises or a VM). Enables ADF to connect to SQL Server, Oracle, SAP, or any other system not publicly accessible from Azure. The SHIR connects outbound to ADF — no inbound firewall ports needed.
Azure-SSIS Integration Runtime — a managed cluster that runs legacy SSIS packages. Use this if you are migrating existing SSIS ETL to Azure without rewriting it.
# Create an ADF instance with Azure CLI
az datafactory create \
--resource-group rg-data-platform \
--factory-name adf-mycompany-prod \
--location eastus
# Create an Azure Integration Runtime (default - always exists)
# No creation needed - Azure IR is built in
# Create a self-hosted Integration Runtime definition in ADF
az datafactory integration-runtime create \
--resource-group rg-data-platform \
--factory-name adf-mycompany-prod \
--name SelfHostedIR \
--type SelfHosted
# Get the authentication key to register the SHIR agent on your server
az datafactory integration-runtime list-auth-key \
--resource-group rg-data-platform \
--factory-name adf-mycompany-prod \
--name SelfHostedIRTriggers: how pipelines are started
ADF supports four trigger types:
- Schedule trigger — runs a pipeline on a cron schedule (e.g., daily at 2 AM UTC). Multiple pipelines can share one trigger.
- Tumbling window trigger — like a schedule trigger but with non-overlapping, fixed-size time windows. Each run receives the window start and end times as parameters. Handles backfill: if ADF was down, it runs all missed windows sequentially when it recovers.
- Storage event trigger — runs when a file is created or deleted in Azure Blob Storage or ADLS Gen2. Use this for event-driven ingestion: process a file as soon as it lands.
- Custom event trigger — runs in response to a custom event published to Azure Event Grid. Use this for complex event-driven orchestration scenarios.
ADF vs Synapse Pipelines: which to use
Synapse Pipelines is functionally identical to ADF — it uses the same underlying engine, the same connectors, and the same activity types. The choice is about context:
Use Synapse Pipelines when your data destination is primarily Synapse (dedicated pool, ADLS Gen2 backing a Synapse workspace). Being co-located with your pools lets you trigger Synapse notebooks, invoke stored procedures, and monitor everything in one place without cross-service configuration.
Use standalone Azure Data Factory when your pipelines serve multiple destinations that are not tied to a single Synapse workspace — for example, feeding data to Cosmos DB, multiple SQL databases, and a data lake simultaneously. ADF also has slightly better support for some enterprise features like Git integration and CI/CD at the factory level.
Common mistakes
- Running all activities sequentially when they could run in parallel. By default, if you drag activities onto the canvas without connecting them with dependency arrows, ADF runs them in parallel. If you connect them all in a chain, they run sequentially. Design pipelines with parallelism in mind — loading 10 tables can be 10x faster with parallel Copy Activities.
- Not using parameterised pipelines. Building one pipeline per table (e.g., one for orders, one for customers, one for products) leads to dozens of nearly-identical pipelines. Use parameters to build one generic pipeline that accepts table name, source query, and destination path as parameters, then invoke it in a ForEach loop.
- Ignoring Data Integration Units (DIUs) for large Copy Activities. The default DIU count is 4. For copying large datasets, increasing DIUs (up to 256) dramatically speeds up the copy at the cost of more DIU-hours. Test with higher DIU counts for your largest tables and find the sweet spot.
- Not setting retry policies on activities. Network blips and transient service failures happen. Set retry count to 3 and retry interval to 30 seconds on all Copy Activities. ADF will automatically retry failed activities without human intervention.
Summary
- Azure Data Factory orchestrates data movement and transformation across 90+ sources and destinations.
- Core building blocks: linked services (connections), datasets (data pointers), activities (steps), pipelines (workflows), and triggers (schedulers).
- The Copy Activity moves data; Mapping Data Flows transform data visually using compiled Spark code.
- Use the self-hosted integration runtime to connect to on-premises or private network data sources.
- Synapse Pipelines is the same engine as ADF — choose Synapse Pipelines if your work is Synapse-centric, standalone ADF for multi-destination orchestration.
- Parameterise pipelines and use ForEach loops to avoid maintaining dozens of identical pipeline definitions.
Frequently asked questions
What is the difference between Azure Data Factory and Synapse Pipelines?
Synapse Pipelines is the same pipeline engine as Azure Data Factory, embedded inside a Synapse workspace. The UI, connectors, and activities are identical. The main difference is that Synapse Pipelines is co-located with your SQL pools and Spark pools, while ADF is a standalone service. Use Synapse Pipelines if you already use Synapse; use standalone ADF if you need pipelines that serve multiple destinations not connected to a single Synapse workspace.
What can Azure Data Factory connect to?
ADF has 90+ native connectors including Azure SQL Database, Synapse Analytics, Cosmos DB, Blob Storage, ADLS Gen2, SQL Server on-premises, Oracle, SAP, Salesforce, Dynamics 365, Google BigQuery, Amazon S3, Snowflake, REST APIs, and more. The self-hosted integration runtime extends connectivity to on-premises and private network sources.
Does ADF transform data or just move it?
ADF can both move and transform data. The Copy Activity moves data with optional column mapping and type conversion. Mapping Data Flows provide a code-free transformation canvas that generates and runs Spark jobs under the hood. You can also invoke external compute for transformation — Databricks notebooks, Azure Functions, Synapse stored procedures, HDInsight Hive, and others.