Triggers in ADF: Schedule, Tumbling Window and Event
The four Azure Data Factory trigger types — schedule, tumbling window, storage event and custom event — compared on what they guarantee, with a decision table, trigger JSON you can adapt, and the settings that cause missed or duplicate runs.
GloryTecks Team
Training & Placement Faculty
Last updated: 24 September 2026
A pipeline in Azure Data Factory does nothing until something starts it. Apart from a manual run, that something is a trigger, and the trigger type decides more than timing. It decides whether missed periods are ever processed, whether failed runs are retried, and how many runs can overlap. ADF has three families of trigger: schedule, tumbling window and event-based, with event-based split into storage events and custom events (Microsoft Learn: pipeline execution and triggers).
The four trigger types
| Trigger | Starts a run when… | Pipelines per trigger | Typical use |
|---|---|---|---|
| Schedule | A wall-clock time arrives (every 15 minutes, daily at 06:00, Mondays and Thursdays…) | Many — and one pipeline can have many triggers | Jobs that only need to run "now, on a timetable" |
| Tumbling window | A fixed-size, non-overlapping time window closes | Exactly one | Loading data period by period, where every period must be processed once |
| Storage event | A blob is created or deleted in a storage account | Many | Processing files as they land |
| Custom event | An event arrives on an Event Grid custom topic | Many | Starting a pipeline from another application or system |
Schedule vs tumbling window: the difference that matters
Both fire on a clock, so they look interchangeable in the UI. They are not. A schedule trigger is fire-and-forget: its run is marked successful as soon as the pipeline run starts, whatever happens next. A tumbling window trigger run waits for the pipeline and takes on its outcome, so a failed or cancelled pipeline shows as a failed or cancelled window.
| Behaviour | Tumbling window | Schedule |
|---|---|---|
| Past periods (backfill) | Supported: set a start time in the past and every missed window runs | Not supported: only the current time and the future |
| Gaps | None: every window from the start date is scheduled | Possible |
| Retries | Configurable retry policy (default 0) | None |
| Concurrency | You set it: 1 to 50 simultaneous windows | Not configurable |
| Window boundaries in the pipeline | trigger().outputs.windowStartTime and windowEndTime | Only trigger().scheduledTime and trigger().startTime |
Comparison from Microsoft Learn: trigger type comparison. The practical rule: if your pipeline loads "the data for a period" (yesterday's orders, the last hour of logs), use a tumbling window and pass the window boundaries into the query. If it simply needs to run at a time, and a skipped run does not leave a hole in your data, a schedule trigger is enough.
Passing the window into the pipeline
A tumbling window trigger maps its window boundaries onto pipeline parameters. The pipeline then filters its source on exactly that range, so re-running a window re-loads the same slice instead of "whatever arrived since the last run":
{
"name": "HourlyOrdersWindow",
"properties": {
"type": "TumblingWindowTrigger",
"typeProperties": {
"frequency": "Hour",
"interval": 1,
"startTime": "2026-09-01T00:00:00Z",
"delay": "00:10:00",
"maxConcurrency": 4,
"retryPolicy": { "count": 2, "intervalInSeconds": 300 }
},
"pipeline": {
"pipelineReference": { "type": "PipelineReference", "referenceName": "LoadOrders" },
"parameters": {
"windowStart": { "type": "Expression", "value": "@{trigger().outputs.windowStartTime}" },
"windowEnd": { "type": "Expression", "value": "@{trigger().outputs.windowEndTime}" }
}
}
}
}Inside LoadOrders, the source query uses those parameters, for example WHERE order_ts >= '@{pipeline().parameters.windowStart}' AND order_ts < '@{pipeline().parameters.windowEnd}'. The half-open range (>= start, < end) stops a row on the boundary being loaded twice. delay holds each window back for ten minutes after it closes, which gives late-arriving rows time to land (Microsoft Learn: tumbling window trigger).
Decide the window size before you create the trigger
The frequency and interval of a tumbling window trigger cannot be changed after it is created. Frequency can be minutes, hours or months. And a start time in the past produces a backfill: the trigger generates one run per missed window, in parallel up to maxConcurrency, before any future windows. A start date a year back on an hourly trigger is almost 9,000 pipeline runs.
Backfill ordering, dependencies between tumbling window triggers and self-dependency (a window waiting for the previous one) are covered in tumbling window triggers: backfills and dependencies.
Schedule triggers and time zones
A schedule trigger can express calendars a tumbling window cannot: specific hours, weekdays, month days, or "the first Monday of the month". The part that trips people up is time zones (Microsoft Learn: schedule trigger):
- In UTC, start and end times need the
Zsuffix (2026-09-01T00:30:00Z); without it, activating the trigger fails. - In any other time zone, they are written without the
Z(2026-09-01T06:00:00) and interpreted in the zone you name. - Changing the time zone setting does not change the start date for you.
- Daylight-saving adjustment only applies to recurrences of a day or longer. India Standard Time has no daylight saving, so an IST schedule never shifts.
{
"name": "DailyFinanceExtract",
"properties": {
"type": "ScheduleTrigger",
"typeProperties": {
"recurrence": {
"frequency": "Day",
"interval": 1,
"startTime": "2026-09-01T00:00:00",
"timeZone": "India Standard Time",
"schedule": { "hours": [6], "minutes": [30] }
}
},
"pipelines": [
{ "pipelineReference": { "type": "PipelineReference", "referenceName": "ExtractFinance" } }
]
}
}This runs ExtractFinance every day at 06:30 IST. Note the pipelines array: a schedule trigger can start several pipelines, and a pipeline can be attached to several schedule triggers.
Event triggers: storage and custom
A storage event trigger subscribes, through Azure Event Grid, to "blob created" and/or "blob deleted" events on a storage account (Microsoft Learn: storage event trigger). Filters on the blob path (Blob path begins with, Blob path ends with) narrow it to one folder or file type, and ignoreEmptyBlobs stops zero-byte files from starting runs. The pipeline receives the arriving file's location in @triggerBody().folderPath and @triggerBody().fileName, which you pass on as parameters so the pipeline processes exactly that file.
- The subscription must be registered with the Event Grid resource provider, and whoever creates the trigger needs permission to create Event Grid subscriptions on the storage account (Owner or Contributor on the account, or the specific
Microsoft.EventGrid/EventSubscriptions/Writepermission). - A storage account supports at most 500 storage event triggers, an Event Grid limit.
- Stopping and restarting an event trigger resumes its old pattern and can fire unwanted runs; Microsoft recommends deleting it and creating a new one instead.
A custom event trigger listens to an Event Grid custom topic that your own applications publish to, and filters on the event subject and type, with up to 5 advanced filters and 25 filter values per trigger (Microsoft Learn: custom event trigger). It suits "start this pipeline when that system says so", without polling. Setting up Event Grid for both kinds is walked through in event-based triggers with Azure Event Grid and ADF.
Choosing a trigger
- Does each run process a specific time period, and must every period be processed exactly once? Tumbling window.
- Does the work start when a file lands? Storage event, with the file path passed to the pipeline.
- Does another system decide when the work starts? Custom event.
- Otherwise, for jobs that just run on a timetable (a nightly refresh, a weekly export), use a schedule trigger.
Mistakes that cause missed or duplicate runs
- Saving a trigger but not publishing it: the trigger takes effect only after you publish, not when you save it in the UI.
- Loading "everything since the last run" from a schedule trigger. One failed run, and the next run cannot tell what was missed. Use a tumbling window with explicit boundaries.
- Using a closed range (
<=end) with window parameters, so boundary rows load twice. - A storage event trigger on a folder that also receives temporary or zero-byte files. Filter by extension and ignore empty blobs.
Can one ADF pipeline have more than one trigger?
How do I reprocess a failed hour?
Why did my new tumbling window trigger start hundreds of runs?
Which storage accounts support storage event triggers?
Where to go next
If you have not built the pipeline yet, start with ADF pipelines explained: building your first pipeline. Azure Data Factory is part of the Azure module in our Data Engineering course.
Sources
- Pipeline execution and triggers — Microsoft Learn
- Create a trigger that runs a pipeline on a schedule — Microsoft Learn
- Create a tumbling window trigger — Microsoft Learn
- Create a storage event trigger — Microsoft Learn
- Create a custom event trigger — Microsoft Learn
GloryTecks Team
Training & Placement Faculty
The GloryTecks faculty team mentors learners across Data Science, AI and Data Engineering, with a focus on real-time projects and placement readiness in Hyderabad.
Want to master Azure Data Factory?
Join GloryTecks’ expert-led Data Engineering training in Hyderabad with real-time projects and 100% placement support.
Copy Activity in Azure Data Factory: A Practical Guide
NextLinked Services in Azure Data Factory Explained
Related articles
ADF Pipelines Explained: Building Your First Pipeline
A beginner's guide to pipelines in Azure Data Factory: what a pipeline and an activity are, the three kinds of activity, the objects you create for a first copy from blob storage to a SQL table, the JSON behind the canvas, why Debug moves real data, what Publish does, and how to read a run's output.
Mapping Data Flows in ADF: Transformations Without Code
Mapping data flows let you design transformations on a canvas in Azure Data Factory and run them on Spark clusters the service manages. This guide explains how they work, walks through one flow stage by stage with real row counts, and sets out when a data flow is the right tool.
ADF Control Flow: ForEach, If and Until Activities
Control flow activities turn a list of steps into logic. This guide covers the four that do most of the work in Azure Data Factory: ForEach for loops, If Condition and Switch for branching, and Until for polling, with each one's properties and documented limits, a JSON example, the nesting rule and concurrency traps.