Generated banner for N8n Loops Official
Generated logo for N8n Loops Official

N8n Loops Official

n8nOfficialPublished by n8n

  • Skill
  • Tool integration
  • Automation and integrations
  • Apache-2.0
  • No issues found

From the author

Use when working with multi-item data, batches, paginated APIs, rate-limited APIs, fan-out across multiple branches, anything that needs to "do this for each", or any time the user mentions looping, iterating, batching, paging, parallelism, or "loop over items". Triggers on "loop", "iterate", "for each", "batch", "page through", "paginate", "rate limit", "process all", "fan-out", "parallel branches", "concurrency", or any node that should run once vs once-per-item.
— the description by n8n

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides the definitive guide to handling multi-item data in n8n. It clarifies the distinction between implicit per-item iteration, single-fire execution, and explicit batching. It teaches users how to leverage built-in node behaviors, the Loop Over Items node, and HTTP pagination to build efficient, scalable, and error-resistant automation pipelines.

What it does

  • Explains the default per-item iteration behavior of n8n nodes.
  • Defines when and how to use the executeOnce setting to prevent redundant processing.
  • Provides a decision tree for selecting the correct looping mechanism.
  • Details the configuration of the Loop Over Items node for batching and rate limiting.
  • Outlines native HTTP Request pagination for efficient API data retrieval.
  • Identifies common anti-patterns like unnecessary loops and double-webhook responses.

When to use it

  • When you need to process data in batches or chunks.
  • When an API requires pagination to fetch all records.
  • When a node should run exactly once regardless of the number of input items.
  • When you need to implement rate limiting or delays between processing steps.
  • When you need to perform stateful iteration or complex multi-branch convergence.

Advantages

  • Prevents common performance issues caused by redundant node executions.
  • Reduces API consumption by utilizing native pagination instead of manual loops.
  • Improves workflow readability by removing unnecessary loop nodes.
  • Ensures reliable data aggregation and notification handling.
  • Provides clear patterns for complex tasks like recursive sub-workflows.

Usage examples

“How do I make sure my Slack notification only sends once after processing 50 items?”
The agent will instruct you to enable the executeOnce setting on the Slack node, ensuring it fires once for the entire dataset rather than once per item.
“I need to process 1000 records from an API that returns 50 items per page. How do I get them all?”
The agent will guide you to use the HTTP Request node's built-in Pagination option, configuring it to automatically fetch all pages until the API returns an empty response.
“How can I send emails in batches of 10 with a delay between each batch?”
The agent will show you how to use the Loop Over Items node with a batchSize of 10, followed by a Wait node, to control the flow and rate of your email sends.
“I have a loop that is running too many times, what should I do?”
The agent will help you determine if you can delete the Loop Over Items node entirely and rely on n8n's default per-item iteration, or if you need to adjust your merge logic.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/n8n-io/n8n-loops-official/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip n8n-loops-official.zip -d .agents/skills

Documentation by n8n

n8n Loops

Three meanings of "loop" map to three mechanisms:

  1. "Run this node for every item." Default. Most nodes loop automatically, so do nothing.

  2. "Run this node once with all items, not once per item." The executeOnce setting (single boolean).

  3. "Process items in explicit batches with control flow between iterations." The Loop Over Items node (formerly Split In Batches).

For paginated APIs, the HTTP Request node has built-in pagination. Almost always preferable to a hand-built page-counting loop.

The model: items are an array

Data flows between nodes as an array of items, each { json: {...}, binary?: {...} }. 50 items = 50-entry array.

Default: a node runs once per item. An HTTP Request with 50 input items fires 50 requests and outputs 50 result items. This is the implicit loop most workflows rely on.

The input array is the loop. Control iteration by controlling the array.

Non-negotiable

executeOnce: true whenever a node should fire once-per-run, not once-per-item. Includes any expression aggregating across the dataset via $input.all() / $('Node').all() plus .map() / .filter() / .reduce() (without it, the aggregate computes N times for N upstream items, often producing N duplicates downstream). Also includes single notifications, aggregate writes, summary messages.

Counter-case: .all() combined with another node's .item (a per-item lookup, e.g., $('Get Tags').all().filter(tag => $('Search Posts').item.json.tag_ids.includes(tag.json.id))) is real per-item work and should keep executeOnce off. See the n8n-expressions-official skill's executeOnce section for the full distinction.

Strong defaults

  • Don't build a loop when default iteration suffices. Most nodes (HTTP Request, native service nodes, Set, IF/Switch) run once per input item automatically: N items in, N runs. To make N HTTP calls or create N records, just connect the source to the node. Don't reach for Loop Over Items unless you need per-iteration control. (Note: Execute Workflow is the exception. It defaults to a single all-items batch. See n8n-subworkflows-official for mode: 'each'.)

  • For paginated APIs, use HTTP Request's built-in pagination. Don't reinvent with Loop Over Items + manual $pageCount unless the API is genuinely odd. See references/HTTP_PAGINATION.md.

  • Loop Over Items is for explicit batching or per-iteration control (rate limiting, per-batch error recovery, stateful chunks, polling). See references/LOOP_OVER_ITEMS.md.

  • Per-item iteration is sequential, not parallel. Each item completes before the next starts, even on parallel looking branches. For a real concurrency pattern, see n8n-subworkflows-official.

Decision tree: which mechanism do I need?

Need to do something for each item?
├── Default per-item iteration is enough
│   └── Just connect the node. Done.
│
├── The node should run once total, not once per item?
│   └── Set executeOnce: true on the node
│
├── Paginated API (multiple HTTP calls to fetch all pages)?
│   └── Use HTTP Request's Pagination option (see references/HTTP_PAGINATION.md)
│
├── Need explicit batching (rate limit, chunk size, per-batch error handling)?
│   └── Use Loop Over Items node (see references/LOOP_OVER_ITEMS.md)
│
└── Need to recurse / repeat with state until a condition is met?
    └── Loop Over Items with Reset, OR a sub-workflow that calls itself.
        Both are advanced patterns; see references/LOOP_OVER_ITEMS.md.

executeOnce: the single-fire setting

Every node's Settings tab has an Execute Once toggle. When on, the node runs once using only the first input item. In SDK code, set executeOnce: true as shown; on an existing workflow, apply it via update_workflow setNodeSettings (n8n 2.24.0+).

{
    name: 'Aggregate Slack',
    type: 'n8n-nodes-base.slack',
    parameters: { /* ... */ },
    executeOnce: true,
}

When to use it:

  • Notifications and aggregate writes. A "summary message" shouldn't fire 100 times because 100 items came in.

  • Counters, totals, reports. Anything computing $input.all().length etc. should run once.

  • Expressions aggregating across the full array via $input.all() / $('Node').all(). Otherwise the aggregate runs per upstream item. (Per-item lookups using .all() filtered by another node's .item are the counter-case, see n8n-expressions-official.)

When NOT to use it:

  • Per-item operations. One notification per item is the default and usually correct.

  • HTTP requests fanning out per item. You want one call per item.

Most common mistake: forgetting executeOnce on an aggregate node, then seeing the same message fire 50 times after a fan-out.

When the implicit loop bites you

Default per-item iteration is great until it isn't. Common surprises:

A "single" config node fires per item

A Set node after a fan-out runs once per item, producing N copies of the same constants. Usually fine, but expensive expressions (long JSON.stringify, Luxon parse) run N times. Move the Set above the fan-out, or set executeOnce: true.

An aggregate Code node runs N times

A Code node reading $input.all() to compute a sum runs once per upstream item without executeOnce: true, producing N identical items. Set executeOnce: true.

A respond-to-webhook fires twice

Most painful version. Respond-to-Webhook fires per input item, and two branches converging without a merge fire it twice: first response wins, the rest log errors. Merge first, or ensure only one branch reaches the responder. See n8n-node-configuration-official references/MERGE_NODE.md.

An LLM call fires N times when you wanted one summary

Same shape as the aggregate Code node. An LLM node with $input.all() in its prompt makes N identical calls, costs N tokens, returns N identical answers without executeOnce: true.

When to reach for Loop Over Items

Default iteration handles most cases. Use Loop Over Items for:

  • Rate limiting. "Process 10 at a time, 1s wait between batches."

  • Batched API calls with array bodies. "Send 50-item chunks to /bulk."

  • Per-batch error handling. "If a batch fails, log and continue."

  • Stateful iteration. "Each iteration depends on the previous output."

  • Polling a long-running job. "Start, check status every 30s until done or capped." Uses reset: true plus a $runIndex ceiling.

  • Per-item multi-branch with aggregation. "For each input, run transforms in parallel, merge, then aggregate." The done output (index 0) carries the result.

For wiring details, the output-index gotcha (output 0 = done, output 1 = loop), and worked examples, see references/LOOP_OVER_ITEMS.md.

When NOT to reach for Loop Over Items

The most common rationalization: "I need to wait for all items to finish before the next step, so I'll add Loop Over Items and use the done output." You don't need Loop Over Items for that. Default per-item iteration already waits: each item flows through the full downstream chain before the next item starts, and the post-loop node never fires "early."

The cure for that mistake is almost always: delete the Loop Over Items node, change nothing else, ship. That is Scenario 1 below, and it covers the majority of cases.

The four scenarios are independent. Read them as separate decisions, not as alternatives that all "replace" Loop Over Items. Most builds hit Scenario 1 and are done. Scenarios 2 and 3 only enter the picture when their specific goal applies. Scenario 4 is the narrow case where Loop Over Items actually earns its place.

Scenario 1: default per-item iteration (the default, most common)

Source emits N items, per-item processor runs N times, downstream chain follows. No Loop Over Items, no executeOnce, no Aggregate. Just connect the nodes.

[Source: 20 items]
  → [Per-item processor]   # default iter, runs 20 times
  → [Next step]            # runs after each item, in order

If a Loop Over Items + done was added here "to wait for all items" or "to make the next node run for each item," delete the Loop Over Items node and wire source straight to processor. Do not replace it with anything. Default iteration already does the job. The exception is Execute Workflow (sub-workflow): it defaults to a single all-items batch, so per-item invocation needs mode: 'each' on that node, not a Loop. See n8n-subworkflows-official.

Scenario 2: a downstream node should fire once total (executeOnce: true)

Independent of Scenario 1. Triggered only when there is a SPECIFIC downstream node whose job is once-per-run, not once-per-item: one digest email after 20 papers process, one summary write after the loop, one final Slack notification.

Set executeOnce: true on that node. The node receives all upstream items but runs once. This is a per-node setting, not a Loop replacement: the per-item processor in Scenario 1 still runs N times, and only this one downstream node collapses.

Scenario 3: a node needs the items as a single array (Aggregate)

Independent of Scenario 1. Triggered only when a downstream node's input contract is a list, not per-item invocations (e.g., a node taking a JSON array body, an LLM prompt that needs the whole list).

Use the Aggregate node to collapse the per-item stream into one item containing the array. Again, not a Loop replacement.

Scenario 4: genuine batching (the only time Loop Over Items earns its place)

Rate limiting (process N at a time with a Wait between batches), chunked bulk API calls (POST 50-item arrays to /bulk), per-batch error handling, polling a long-running job with reset: true and a $runIndex ceiling, stateful iteration where each batch depends on the previous output.

"Wait for items to finish" does not qualify. Default iteration already does that.

Quick disambiguation

If your only reason for the Loop is "wait for items / run for each item," you are in Scenario 1. Delete the Loop. Do not add executeOnce or Aggregate as a substitute. They solve different problems and are only added when their own scenario applies.

When to reach for HTTP pagination

Three common page shapes:

  • Next-URL in response. Each response includes a next link.

  • Page number/cursor parameter. Bump ?page=N or ?cursor=... each call.

  • Stop on empty page or specific status.

HTTP Request handles all natively via its Pagination option: set the mode, give a next-page expression, and the node loops internally, returning a single output array of all pages' items.

Don't reinvent with Loop Over Items + manual $pageCount unless the API does something the built-in modes can't express.

See references/HTTP_PAGINATION.md.

Sub-workflow recursion

For genuinely recursive work (tree walking, retry-with-backoff, "process this and its children"), a self-calling sub-workflow is cleaner than Loop Over Items with Reset. Input parameters carry recursion state.

Sub-workflow: Walk Tree
  inputs: { node_id, depth }
  body: process node, look up children, for each child call self with depth+1

Watch recursion depth. n8n has nested-execution limits. For deep recursion, a queue + flat loop beats true recursion.

Reference files

FileRead when
references/LOOP_OVER_ITEMS.mdConfiguring the Loop Over Items node, batching, rate limiting, stateful iteration
references/HTTP_PAGINATION.mdCalling a paginated API, configuring HTTP Request pagination modes

Anti-patterns

Anti-patternWhat goes wrongFix
Adding Loop Over Items to "make it loop" when default iteration already doesWorkflow harder to read for no benefit, and loop output vs done output gets miswiredJust connect the node directly and let default iteration handle it
Aggregate Code node without executeOnceSame aggregate computed N times, output has N identical itemsSet executeOnce: true
Manual pagination loop with Loop Over Items + $pageCountReinvents what HTTP Request does natively, with brittle stop conditionsUse HTTP Request's Pagination option
Sending one Slack message per item when you wanted a summarySlack channel floods, rate limits hit, embarrassmentexecuteOnce: true on the Slack node, build the summary upstream
Two branches both reach Respond to WebhookResponds twice, downstream callers see errorsMerge before the responder, or ensure only one branch reaches it
Loop Over Items with Reset and no clear terminationInfinite loop, n8n eats memory until the execution is killedAlways have a clear termination condition. Prefer HTTP pagination for paged APIs
Nesting one Loop Over Items inside another in the same workflowBroken at runtime, validation passesMove the inner loop into a sub-workflow called per outer iteration. See n8n-subworkflows-official mode: 'each'

Files

LICENSE

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for describing the origin of the Work and
      reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may accept and charge a
      fee for accepting support, warranty, indemnity, or other liability
      obligations and/or rights consistent with this License. However, in
      accepting such obligations, You may act only on Your own behalf
      and on Your sole responsibility, not on behalf of any other
      Contributor, and only if You agree to indemnify, defend, and hold
      each Contributor harmless for any liability incurred by, or claims
      asserted against, such Contributor by reason of your accepting any
      such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright 2026 n8n GmbH

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
   implied. See the License for the specific language governing
   permissions and limitations under the License.

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs Node.js

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
n8n
Publisher
n8n (Official)
Source
n8n-io/skills · skills/n8n-loops-official · commit 27b6b9f
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by n8n.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download n8n-loops-official.zip