Trigger types: which one to choose when
The trigger is a workflow's entry point, and the choice usually comes down to one question: who announces the event?
- Nobody does; the time has simply come → Schedule Trigger
- An external system announces it → Webhook or that service's own trigger node
- A person starts it → Manual Trigger or the n8n Form Trigger
- Another workflow calls it → Execute Sub-workflow Trigger
This is an architectural decision rather than a technical one: it is the difference between polling (you go and ask) and push (the system tells you).
| Trigger | When it fires | Typical use |
|---|---|---|
| Manual Trigger | When you press "Execute workflow" | Building and testing; one-off data migrations |
| Schedule Trigger | On an interval or cron expression | Daily reports, hourly syncs, monitoring |
| Webhook | When an HTTP request hits the URL it exposes | Receiving events from systems with no dedicated trigger node; using n8n as an API |
| App trigger (Gmail, Telegram, ...) | When an event happens in the service | A new email, a new message, a new row |
| n8n Form Trigger | When a form n8n hosts is submitted | Internal requests and simple intake forms — no separate site needed |
| Execute Sub-workflow Trigger | When another workflow calls it | A reusable module; a tool for an AI agent |
| Error Trigger | When a workflow it is attached to fails | Centralised failure alerting |
A workflow can have more than one trigger. If you want the same process to run automatically each morning and also on demand, connect both a Schedule Trigger and a Manual Trigger into the same node. Whichever trigger fires, the flow starts from there.
The polling vs push choice in practice: if the service has its own trigger node, use it — it either registers the webhook for you or polls at a sensible interval. Building Schedule Trigger + HTTP Request by hand only makes sense when the service has no node, or when you need custom logic.
The most commonly forgotten part of polling with a Schedule Trigger is remembering where you left off. A "fetch the last hour's records" query loses that hour forever the one time the workflow fails. The reliable approach is to store the timestamp or ID of the last processed record and resume from it next time.
📚 Sources and documentation
- Schedule Trigger nodeofficialdocs.n8n.io
- n8n Form Trigger nodeofficialdocs.n8n.io
- Execute Sub-workflow Triggerofficialdocs.n8n.io