Workflow Loops: Automate Repeating Steps Without Chaos
Repeating the same action across a list — sending an email to each new lead, processing every row in a spreadsheet, updating each record in a database — is where most no-code automations quietly break down. The trigger fires once, but the work needs to happen ten or a hundred times. Workflow loop patterns solve this, and choosing the wrong one creates either duplicate runs, missed items, or a flow that grinds to a halt at item three. This guide covers the three loop patterns that actually work, when to use each, and the mistakes that cause silent failures.
Why loops are harder than they look
A single-run workflow has a clear shape: trigger → action → done. A loop-based workflow has to answer two extra questions every time it runs: what is the current item, and when do I stop?
No-code tools handle this differently. Some give you an explicit "loop" or "iterate" step. Others expect you to fan out with a split, process each branch independently, and rejoin. A few push you toward a recursive trigger — the workflow calls itself. Each approach has a ceiling, and hitting that ceiling mid-production is painful.
The good news is that almost every repeating task fits one of three patterns. Identify which pattern applies before you build, and the implementation becomes straightforward.
The three loop patterns
| Pattern | How it works | Best for | Watch out for |
|---|---|---|---|
| List iterator | A built-in loop step walks through an array item by item | Processing a known, finite list in one run | Large lists can time out; check your tool's item limit |
| Trigger-per-record | Each record fires its own workflow run independently | High-volume processing where failures should be isolated | Harder to track overall progress; need a status field |
| Recursive trigger | The workflow schedules or calls itself after each item | Paginated APIs, unknown list length, rate-limited sources | Requires a clear stop condition or it runs forever |
Picking the wrong pattern is usually the reason a loop "works in testing" but fails in production, where lists are longer and APIs have rate limits.
Pattern 1: List iterator
Use this when your tool offers a native loop or "for each" step and your list has fewer than a few hundred items per run.
Worked example — updating CRM records from a spreadsheet:
- Trigger: Schedule (daily, 08:00).
- Action: Fetch rows from spreadsheet where
status = "pending". - Loop step: Iterate over the returned array.
- Inside the loop: find the matching CRM contact by email. - Inside the loop: update the contact's last_activity field. - Inside the loop: mark the spreadsheet row status = "done".
- End loop.
The key discipline here is marking each item inside the loop before moving to the next. If you batch-update at the end and the run times out at item 47, you have no record of where it stopped, and the next run processes allundefinedagain.
Pattern 2: Trigger-per-record
Use this when volume is unpredictable, failures in one record should not block others, or you want each item to have its own run history for debugging.
The mechanics: an upstream step (a webhook, a database watcher, or a scheduled query) emits one event per record. Each event fires a separate workflow run.
Where this shines: Sending personalised documents. If generating a PDF for contact A fails because of a bad address field, contacts B through Z still get their documents. With a list iterator, a single bad record can halt the entire loop.
The discipline required: You need a status field on the source record. Without it, a re-run of the upstream step will re-emit records that already succeeded. A simple processed_at timestamp column is enough.
If you are evaluating whether your current process fits this pattern, the /analyze tool in CraftMyFlow can map which steps in your existing flow are genuinely independent versus sequentially dependent — that distinction tells you whether trigger-per-record is safe to use.
Pattern 3: Recursive trigger
Use this for paginated API responses, queues of unknown length, or sources that enforce strict rate limits.
The shape: the workflow fetches one page (or one item), processes it, then schedules the next run — passing along a cursor or offset so it knows where to resume.
Stop condition is non-negotiable. The workflow must check a condition before doing any work:
- Is the cursor empty? Stop.
- Has the page returned zero results? Stop.
- Has a maximum run count been reached? Stop.
Without a stop condition, a recursive trigger becomes an infinite loop that burns through your plan's task quota in minutes.
Worked example — pulling all pages from a paginated API:
- Trigger: Webhook (initial kick-off) or scheduled.
- Read cursor value from a persistent store (a database cell, a config record).
- If cursor is null and
page_processedcount >page_processed→ end run. - Fetch API:
GET /contacts?page={{cursor}}. - Process each contact in the response.
- Write
next_cursorfrom the API response back to the persistent store. - Schedule this same workflow to run inundefinedseconds (respecting rate limit).
The /templates section has a pre-built recursive pagination template you can clone and adapt rather than building this from scratch.
The three mistakes that break loops silently
1. No idempotency check. If a run fails halfway and restarts, items already processed get processed again. Add a check: has this item already been handled? A status field or a processed-ID log prevents double-sends and duplicate records.
2. Ignoring the tool's item limit. Most no-code platforms cap list iterators at 500–2000 items per run. A list that isundefineditems today will beundefineditems in six months. Build in a split or switch to trigger-per-record before you hit the ceiling.
3. Errors swallowed inside the loop. A failed step inside a loop often causes the entire loop to skip silently. Configure error handling inside the loop, not just on the workflow as a whole — route failures to a log or a Slack message so you know which item broke and why.
For building out more complex error paths around loops, the /browse page surfaces pre-built error-handling patterns you can drop into an existing flow.
If you are designing a broader automation stack and want to understand how loop-heavy workflows fit alongside other tools, CraftMyStack is useful for mapping which platforms in your setup handle iteration natively versus requiring workarounds.
Key takeaways
- There are three loop patterns — list iterator, trigger-per-record, and recursive trigger — and each fits a different situation. Using the wrong one is the most common cause of loop failures in production.
- Mark items as processed inside the loop, not after it finishes, so partial runs leave a clean record.
- Every recursive trigger needs an explicit stop condition before any other logic runs.
- Idempotency is not optional. Assume any run can fail and restart; build so that a restart does not duplicate work.
- Know your tool's item limit for list iterators and plan for growth now, not when the limit is hit.
- Errors inside loops need their own handling. Workflow-level error catching does not reliably catch item-level failures.
If you have a repeating task that is currently handled manually or with a fragile workaround, open CraftMyFlow and search the loop templates — most of the patterns above have a working starting point you can adapt in under an hour.