Ever found yourself staring at two different streams of data in n8n, wondering how to combine them for use in a further workflow? You're not alone! Two of the most powerful, yet often confused, nodes for these tasks are the Merge node and the Aggregate node.
What is n8n?
Before we get into the nodes, let's quickly cover the basics. n8n is a free, open-source workflow automation tool. It allows you to connect different applications and services to automate repetitive tasks. You can “no-code“ code your entire processes on n8n.
Think of it as a set of digital LEGO blocks; each block (or "node") performs a specific action, and you connect them to build a "workflow" that runs automatically. You can schedule your workflows, set triggers, create webhooks, and do almost anything with it. And combine it with v0, Replit, Lovable and you are untouchable.
What is a Merge Node?
The Merge node is a core n8n node for combining data from two or more separate input streams into a single output. It waits for all connected inputs to provide data before it executes. Think of it as a VLOOKUP/XLOOKUP in a spreadsheet or a JOIN in a SQL database.
Parameters in Merge Node
Append
Stacks data from all inputs one after another into a single, longer list.
- Input 1:
[{ "name": "Alice" }, { "name": "Bob" }]
- Input 2:
[{ "name": "Charlie" }]
- Output:
[{ "name": "Alice" }, { "name": "Bob" }, { "name": "Charlie" }]
Combine
Merges items from two inputs side-by-side based on a specific rule. This is the most common and powerful mode. It has several sub-modes:
-
By Matching Fields: Combines items where a specific field (a "key," like an ID) matches in both inputs. It supports standard join logic:
-
Keep Matches (Inner Join): Only outputs items that have a match in both inputs.
Example:
- Input 1 (Users):
[{ "id": 1, "name": "Alice" }, { "id": 2, "name": "Bob" }]
- Input 2 (Orders):
[{ "userId": 1, "product": "Laptop" }, { "userId": 3, "product": "Mouse" }]
- Match On:
id
from Input 1 anduserId
from Input 2 - Output:
[{ "id": 1, "name": "Alice", "userId": 1, "product": "Laptop" }]
- Input 1 (Users):
-
Keep Non-Matches (~Inner Join): Only outputs items that don’t have a match in both inputs.
Example: Using the same inputs as above.
- Output:
[{ "id": 2, "name": "Bob" }, { "userId": 3, "product": "Mouse" }]
- Output:
-
Keep Everything (Outer Join): Keeps all items from both inputs, regardless of whether they have a match.
Example: Using the same inputs.
- Output:
[{ "id": 1, "name": "Alice", "userId": 1, "product": "Laptop" }, { "id": 2, "name": "Bob" }, { "userId": 3, "product": "Mouse" }]
- Output:
-
Enrich Input 1/2 (Left/Right Join): Keeps all items from the first input and adds data from the second where a match is found.
Example (Enrich Input 1):
- Output:
[{ "id": 1, "name": "Alice", "userId": 1, "product": "Laptop" }, { "id": 2, "name": "Bob" }]
- Output:
-
Keep Matches (Inner Join): Only outputs items that have a match in both inputs.
-
By Position: Merges items based on their order in the list (the first item of Input 1 with the first of Input 2, the second with the second, etc.).
Example:
- Input 1:
[{ "name": "Alice" }, { "name": "Bob" }]
- Input 2:
[{ "age": 30 }, { "age": 25 }]
- Output:
[{ "name": "Alice", "age": 30 }, { "name": "Bob", "age": 25 }]
- Input 1:
-
By All Possible Combinations (Cartesian Product): Creates every possible pairing between items from the inputs.
Example:
- Input 1:
[{ "shirt": "Blue" }, { "shirt": "Red" }]
- Input 2:
[{ "pants": "Jeans" }, { "pants": "Khakis" }]
- Output:
[{ "shirt": "Blue", "pants": "Jeans" }, { "shirt": "Blue", "pants": "Khakis" }, { "shirt": "Red", "pants": "Jeans" }, { "shirt": "Red", "pants": "Khakis" }]
- Input 1:
-
SQL Query: For advanced users, this mode allows you to write a custom SQL query to merge the inputs. The incoming data streams are treated as tables (named
input1
,input2
, etc.).Example:- Query:
SELECT i1.name, i2.product FROM input1 i1 JOIN input2 i2 ON i1.id = i2.userId
- This would produce the same result as the "Keep Matches" example.
- Query:
-
Choose Branch: Waits for both inputs to finish, but then only passes through the data from one of the inputs that you select.
Example:
- Input 1:
[{ "status": "Success" }]
- Input 2:
[{ "data": [1, 2, 3] }]
- Choose: Input 2
- Output:
[{ "data": [1, 2, 3] }]
- Input 1:
What is an Aggregate Node?
The Aggregate node in n8n is used to take multiple separate items and group them together into a single output item. Think of it as zipping multiple files into a single archive; it combines a list of items into one container.
Parameters in Aggregate Node
Individual Fields
This mode allows you to pick a specific field from your incoming items and combine all of its values into a single list. You specify an Input Field Name
(e.g., email
). The node then collects the value of the email
field from every incoming item and creates a single output item containing a new field with a list (array) of all those email addresses.
-
Disable Dot Notation: Turning on
Disable Dot Notation
tells n8n to treat field names literally. It will no longer interpret a dot as a way to access nested levels.Example:- Input:
[{ "user.email": "test@example.com" }]
- With Dot Notation (default): n8n looks for a
user
object with anemail
key. It finds nothing. - With
Disable Dot Notation
ON: n8n looks for a field literally named"user.email"
and finds it.
- Input:
-
Merge Lists: This option is for when the field you are trying to aggregate is already a list (an array) in each item. When enabled,
Merge Lists
takes all the items from these individual lists and combines them into one single, "flat" list.Example:- Input:
[{ "tags": ["A", "B"] }, { "tags": ["C"] }]
Merge Lists
OFF:[{ "tags": [["A", "B"], ["C"]] }]
(a list of lists)Merge Lists
ON:[{ "tags": ["A", "B", "C"] }]
(a single list)
- Input:
-
Include Binaries: "Binary data" usually refers to files (like images, PDFs, CSVs). When a node downloads a file, it's attached to the item as binary data. Many nodes that process data ignore these file attachments by default to keep things fast. Turning on
Include Binaries
forces the node to keep and pass along any files attached to the items it is processing.Example: If you read 3 image files, you get 3 items, each with binary data. Aggregating them with this option ON results in one item with all 3 image files attached. -
Keep Missing And Null Values: This option controls how the node handles items where the field you're targeting is either completely missing or has a value of
null
. When enabled, the node will add anull
entry to your final aggregated list for every item that had a missing or null value.Example:- Input:
[{ "email": "a@a.com" }, { "email": null }, { "name": "Bob" }]
Keep Missing...
OFF:[{ "email": ["a@a.com"] }]
Keep Missing...
ON:[{ "email": ["a@a.com", null, null] }]
- Input:
All Item Data
This mode takes all the incoming items and groups them entirely into a list, which is then placed inside a single output item.
Sounds confusing, right? Let us break this down.
The Core Difference: Merge vs. Aggregate
The core difference is simple:
- Merge: Combines data from two or more sources horizontally (adds more columns/properties to existing items). It's about enriching data.
- Aggregate: Summarizes data from one source vertically (reduces the number of rows/items into a single item). It's about grouping data.
Imagine you have two lists:
- Users:
[{ "id": 1, "name": "Alice" }, { "id": 2, "name": "Bob" }]
- Purchases:
[{ "userId": 1, "item": "Book" }, { "userId": 1, "item": "Pen" }]
- Using a Merge Node (in "Enrich Input 1" mode, matching
id
anduserId
), you would get two items, with data combined where it matches:[{ "id": 1, "name": "Alice", "item": "Book" }, { "id": 1, "name": "Alice", "item": "Pen" }, { "id": 2, "name": "Bob" }]
- Notice how Alice's data was duplicated to match each of her purchases.
- Using an Aggregate Node on the Purchases list (aggregating the
item
field), you would get one item that summarizes the list:[{ "item": ["Book", "Pen"] }]
When to Use These Nodes Together
The most common and powerful use case is using them in sequence: Merge first, then Aggregate. This pattern allows you to enrich your data before you summarize it.
- Get Users: Fetch a list of all users from your database.
[{ "id": 1, "name": "Alice" }, { "id": 2, "name": "Bob" }]
- Get Purchases: Fetch a list of all purchases.
[{ "userId": 1, "product": "Laptop" }, { "userId": 1, "product": "Mouse" }, { "userId": 2, "product": "Keyboard" }]
- Merge Node: Merge the two lists using "Keep Matches" on
id
anduserId
.- Output:
[{ "id": 1, "name": "Alice", "product": "Laptop" }, { "id": 1, "name": "Alice", "product": "Mouse" }, { "id": 2, "name": "Bob", "product": "Keyboard" }]
- Output:
- Aggregate Node: Now, group this merged data. You can't use the standard Aggregate node for this, but you can use a Code Node or a loop to achieve the grouping. The conceptual result you want is:
- Desired Output:
[{ "name": "Alice", "products": ["Laptop", "Mouse"] }, { "name": "Bob", "products": ["Keyboard"] }]
- Desired Output:
When to Not Use Merge and Aggregate Nodes
- Don't use Merge if... you just want to combine two lists into one longer list without matching them (like the
Append
mode example). In this case, you can often just let the data from both sources flow into the next node, and n8n will process them sequentially. - Don't use Aggregate if... you aren't summarizing or calculating anything. If you just need to transform data within each item (e.g., format a date or change a text case), the Set or Code node is a better choice.
Now that you have understood the difference, go and build something!
Frequently Asked Questions (FAQs)
What's the difference between Merge's "Append" mode and just connecting two nodes to a third one?
Append
mode waits for all inputs to finish and then combines them into a single, ordered list. Simply connecting two nodes to a third will make the third node run once for each incoming item, processing them as they arrive, not as a single combined batch.
Can the Merge node handle more than two inputs?
Yes! You can connect multiple nodes to the Merge node. The Append
mode works seamlessly with multiple inputs. The Combine
mode will merge the first two inputs, then merge the result with the third, and so on.
Why would I use "Merge by Position"? It seems risky.
It's useful when you have two data sources that don't share a common key but you know they are in the exact same order. For example, one node outputs a list of names, and another node (from a different system) outputs a corresponding list of emails in the same order.
What happens in a Merge if a match is found for multiple items?
It creates a new combined item for every possible match. If one user in Input 1 matches three orders in Input 2, you will get three output items for that user, each merged with one of the three orders.
What is the difference between Aggregate's "Individual Fields" and "All Item Data"?
"Individual Fields" plucks the value from a specific field (like email
) from every item and puts those values into a list. "All Item Data" takes the entire item object for every item and puts those objects into a list.
Does the Aggregate node change the original data?
No, it consumes the incoming items and produces a new, single output item that contains the aggregated data. The original items are effectively replaced by this new summary item for the rest of the workflow.
How can I perform calculations like SUM or AVERAGE with the Aggregate node?
The standard Aggregate node is for grouping data into lists. To perform calculations like sum, average, or count, you would typically use the Code Node after aggregating to loop through the list and perform the math.
My Merge node isn't producing any output. What's wrong?
The most common reason is that it's waiting for data from all its inputs. Make sure all nodes connected to it have executed successfully. If you're using a matching mode like "Keep Matches," it's also possible that no items actually have matching keys.
Can I merge data from a database and a Google Sheet?
Absolutely. The Merge node is source-agnostic. As long as you have two streams of data items within your workflow, you can merge them, regardless of where they came from.
Is there a limit to how many items the Aggregate node can handle?
The limit is determined by the memory available to your n8n instance. Aggregating a very large number of items (hundreds of thousands) could potentially cause memory issues, especially if the items themselves are large.