first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled

This commit is contained in:
2026-03-17 16:22:57 +03:30
commit 3d5eaf9445
15349 changed files with 2847338 additions and 0 deletions
@@ -0,0 +1,67 @@
{
"createdAt": "2024-09-03T11:51:56.540Z",
"updatedAt": "2024-09-03T12:22:21.000Z",
"name": "Binary Data",
"active": true,
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "binary-files-benchmark",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [0, 0],
"id": "bfe19f12-3655-440f-be5c-8d71665c6353",
"name": "Webhook",
"webhookId": "109d7b13-93ad-42b0-a9ce-ca49e1817b35"
},
{
"parameters": { "respondWith": "binary", "options": {} },
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [740, 0],
"id": "cd957c9b-6b7a-4423-aac3-6df4d8bb571e",
"name": "Respond to Webhook"
},
{
"parameters": {
"operation": "write",
"fileName": "=file-{{ Date.now() }}-{{ Math.random() }}.js",
"dataPropertyName": "file",
"options": {}
},
"type": "n8n-nodes-base.readWriteFile",
"typeVersion": 1,
"position": [260, 0],
"id": "f2ce4709-7697-4bc6-8eca-6c222485297a",
"name": "Write File to Disk"
},
{
"parameters": { "fileSelector": "={{ $json.fileName }}", "options": {} },
"type": "n8n-nodes-base.readWriteFile",
"typeVersion": 1,
"position": [500, 0],
"id": "198e8a6c-81a3-4b34-b099-501961a02006",
"name": "Read File from Disk"
}
],
"connections": {
"Webhook": { "main": [[{ "node": "Write File to Disk", "type": "main", "index": 0 }]] },
"Write File to Disk": {
"main": [[{ "node": "Read File from Disk", "type": "main", "index": 0 }]]
},
"Read File from Disk": {
"main": [[{ "node": "Respond to Webhook", "type": "main", "index": 0 }]]
}
},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": null,
"pinData": {},
"versionId": "8dd197c0-d1ea-43c3-9f88-9d11e7b081a0",
"triggerCount": 1,
"tags": []
}
@@ -0,0 +1,7 @@
{
"$schema": "../scenario.schema.json",
"name": "BinaryData",
"description": "Send a binary file to a webhook, write it to FS, read it from FS and receive it back",
"scenarioData": { "workflowFiles": ["binary-data.json"] },
"scriptPath": "binary-data.script.js"
}
@@ -0,0 +1,29 @@
import http from 'k6/http';
import { check } from 'k6';
const apiBaseUrl = __ENV.API_BASE_URL;
// This creates a 2MB file (16 * 128 * 1024 = 2 * 1024 * 1024 = 2MB)
const file = Array.from({ length: 128 * 1024 }, () => Math.random().toString().slice(2)).join('');
const filename = 'test.bin';
export default function () {
const data = {
filename,
file: http.file(file, filename, 'application/javascript'),
};
const res = http.post(`${apiBaseUrl}/webhook/binary-files-benchmark`, data);
if (res.status !== 200) {
console.error(
`Invalid response. Received status ${res.status}. Body: ${JSON.stringify(res.body)}`,
);
}
check(res, {
'is status 200': (r) => r.status === 200,
'has correct content type': (r) =>
r.headers['Content-Type'] === 'application/javascript; charset=utf-8',
});
}
@@ -0,0 +1,8 @@
{
"type": "httpBearerAuth",
"name": "Dummy HTTP credential",
"data": {
"token": "dummy token"
},
"id": "0fqzOReozl2aQvtl"
}
@@ -0,0 +1,241 @@
{
"name": "Credential HTTP Request",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "benchmark-credential-http-node",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [-64, 32],
"id": "7dd66dcc-03c7-4898-ab3d-d2765730e3f3",
"name": "Webhook",
"webhookId": "92b141cd-6e59-4425-9c0a-e2ee0f4faad2"
},
{
"parameters": {
"respondWith": "allIncomingItems",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [1072, 32],
"id": "e074e6a7-2417-4fde-8b6b-bc68069e833b",
"name": "Respond to Webhook"
},
{
"parameters": {
"url": "http://mockapi:8080/users/clair.bahringer/received_events/public",
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth",
"options": {
"response": {
"response": {
"fullResponse": true
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [304, -176],
"id": "28ddbbf9-56a5-431e-afe9-3c44b21aa676",
"name": "Mock public received events",
"credentials": {
"httpBearerAuth": {
"id": "0fqzOReozl2aQvtl",
"name": "Dummy HTTP credential"
}
}
},
{
"parameters": {
"url": "http://mockapi:8080/repos/udke6pujoywnagxkcvab2riw23khzn2tibo2vincws32qexb50ey7h97d42vnzyol0rxypgsg4pomsf7sgnmdaihstljw8edcijrwmy7mfi76yif19c4/47i31dh737el215j62ts2f2782nw3ss26rul3s8jw13u3vu0xm349a5hyay5asmwnlnf7nx8p9h4g62so6s1cis7xv9puj5j98t4m980sbe2455fn1obccjl/events",
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth",
"options": {
"response": {
"response": {
"fullResponse": true
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [304, 32],
"id": "3ce8827c-6226-467e-a4da-9891c1acd863",
"name": "Mock repository events",
"credentials": {
"httpBearerAuth": {
"id": "0fqzOReozl2aQvtl",
"name": "Dummy HTTP credential"
}
}
},
{
"parameters": {
"url": "http://mockapi:8080/orgs/g02pp066qoyithcjevhd6m1wfii3c4x51k39n9apybljhx69/events",
"authentication": "genericCredentialType",
"genericAuthType": "httpBearerAuth",
"options": {
"response": {
"response": {
"fullResponse": true
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [304, 224],
"id": "a8e416ab-50cc-4e50-8d9a-9fcf5d4bbdc8",
"name": "Mock organization events",
"credentials": {
"httpBearerAuth": {
"id": "0fqzOReozl2aQvtl",
"name": "Dummy HTTP credential"
}
}
},
{
"parameters": {
"numberInputs": 3
},
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [608, 32],
"id": "542a27d4-3a03-4c22-a79a-7266050c519e",
"name": "Merge"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "89608adb-f487-416f-a7d8-3ebb1f7b50e5",
"name": "statusCode",
"value": "={{ $json.statusCode }}",
"type": "number"
}
]
},
"options": {}
},
"id": "35d4bfbb-d4be-49f4-a5dd-bd5c67a48200",
"name": "Select statusCode",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [832, 32]
}
],
"pinData": {
"Webhook": [
{
"json": {
"headers": {
"host": "localhost:5678",
"user-agent": "curl/8.6.0",
"accept": "*/*"
},
"params": {},
"query": {},
"body": {},
"webhookUrl": "http://localhost:5678/webhook-test/benchmark-credential-http-node",
"executionMode": "test"
}
}
]
},
"connections": {
"Webhook": {
"main": [
[
{
"node": "Mock public received events",
"type": "main",
"index": 0
},
{
"node": "Mock repository events",
"type": "main",
"index": 0
},
{
"node": "Mock organization events",
"type": "main",
"index": 0
}
]
]
},
"Mock public received events": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Mock repository events": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"Mock organization events": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 2
}
]
]
},
"Merge": {
"main": [
[
{
"node": "Select statusCode",
"type": "main",
"index": 0
}
]
]
},
"Select statusCode": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "96bfc5ef-9421-47f5-9fdd-432dbd4bc4ca",
"meta": {
"instanceId": "4141065f11bd5ed73fef4f9b1d91842ded0ec4058e6640a98aa14384e269204b"
},
"id": "6V8rTiIDqZOniAs1",
"tags": []
}
@@ -0,0 +1,10 @@
{
"$schema": "../scenario.schema.json",
"name": "CredentialHttpNode",
"description": "Webhook -> 3x HTTP request to a mock API -> Merge -> Respond to Webhook. Requires a mock API running at http://mockapi:8080",
"scenarioData": {
"workflowFiles": ["credential-http-node.json"],
"credentialFiles": ["credential-bearer.json"]
},
"scriptPath": "credential-http-node.script.js"
}
@@ -0,0 +1,30 @@
import http from 'k6/http';
import { check } from 'k6';
const apiBaseUrl = __ENV.API_BASE_URL;
export default function () {
const res = http.post(`${apiBaseUrl}/webhook/benchmark-credential-http-node`);
if (res.status !== 200) {
console.error(
`Invalid response. Received status ${res.status}. Body: ${JSON.stringify(res.body)}`,
);
}
check(res, {
'is status 200': (r) => r.status === 200,
'http requests were OK': (r) => {
if (r.status !== 200) return false;
try {
// Response body is an array of the request status codes made with HttpNodes
const body = JSON.parse(r.body);
return Array.isArray(body) ? body.every((request) => request.statusCode === 200) : false;
} catch (error) {
console.error('Error parsing response body: ', error);
return false;
}
},
});
}
@@ -0,0 +1,168 @@
{
"createdAt": "2025-09-24T12:19:51.268Z",
"updatedAt": "2025-09-24T12:20:45.000Z",
"name": "Data table node",
"active": true,
"nodes": [
{
"parameters": {
"respondWith": "allIncomingItems",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.4,
"position": [688, 0],
"id": "a7eeb256-a47e-4fe9-a0e1-b33015912b15",
"name": "Respond to Webhook"
},
{
"parameters": {
"httpMethod": "POST",
"path": "data-table-node-benchmark",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [-288, 0],
"id": "b54681a1-6cfc-4970-ad33-25cb8fec6936",
"name": "Webhook",
"webhookId": "4748ca75-3b3c-4e4a-8913-3590fdc1867d"
},
{
"parameters": {
"fieldToSplitOut": "body.items",
"options": {}
},
"type": "n8n-nodes-base.splitOut",
"typeVersion": 1,
"position": [96, 0],
"id": "019d451f-604f-4ed6-8f40-1beb86445061",
"name": "Split Out"
},
{
"parameters": {
"dataTableId": {
"__rl": true,
"value": "={{ $('Webhook').item.json.body.dataTableId }}",
"mode": "list"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"isActive": "={{ $json.isActive }}",
"firstName": "={{ $json.firstName }}",
"birthDate": "={{ $json.birthDate }}",
"age": "={{ $json.age }}"
},
"matchingColumns": [],
"schema": [
{
"id": "firstName",
"displayName": "firstName",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "age",
"displayName": "age",
"required": false,
"defaultMatch": false,
"display": true,
"type": "number",
"readOnly": false,
"removed": false
},
{
"id": "birthDate",
"displayName": "birthDate",
"required": false,
"defaultMatch": false,
"display": true,
"type": "dateTime",
"readOnly": false,
"removed": false
},
{
"id": "isActive",
"displayName": "isActive",
"required": false,
"defaultMatch": false,
"display": true,
"type": "boolean",
"readOnly": false,
"removed": false
},
{
"id": "empty",
"displayName": "empty",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.dataTable",
"typeVersion": 1,
"position": [448, 0],
"id": "05a47403-6c7d-4aad-b0eb-ca726e7594c9",
"name": "Insert row"
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Split Out",
"type": "main",
"index": 0
}
]
]
},
"Insert row": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Split Out": {
"main": [
[
{
"node": "Insert row",
"type": "main",
"index": 0
}
]
]
}
},
"pinData": {},
"settings": { "executionOrder": "v1" },
"staticData": null,
"versionId": "cdd59544-4b5d-42c0-a07f-8ab48a9d849c",
"triggerCount": 1,
"tags": [],
"meta": {
"responseMode": "lastNode",
"options": {}
}
}
@@ -0,0 +1,10 @@
{
"$schema": "../scenario.schema.json",
"name": "DataTableNode",
"description": "A Data table node that first inserts 100 items and then reads them from the table. The data is returned with RespondToWebhook Node.",
"scenarioData": {
"workflowFiles": ["data-table-node.json"],
"dataTableFile": "data-table.json"
},
"scriptPath": "data-table-node.script.js"
}
@@ -0,0 +1,38 @@
import http from 'k6/http';
import { check } from 'k6';
const apiBaseUrl = __ENV.API_BASE_URL;
const dataTableId = __ENV.DATA_TABLE_ID;
export default function () {
const res = http.post(`${apiBaseUrl}/webhook/data-table-node-benchmark`, {
dataTableId: dataTableId,
items: Array.from({ length: 100 }, (_, i) => ({
firstName: `Item ${i + 1}`,
age: Math.floor(Math.random() * 100),
birthDate: new Date(),
isActive: i % 2 === 0,
})),
});
if (res.status !== 200) {
console.error(
`Invalid response. Received status ${res.status}. Body: ${JSON.stringify(res.body)}`,
);
}
check(res, {
'is status 200': (r) => r.status === 200,
'has items in response': (r) => {
if (r.status !== 200) return false;
try {
const body = JSON.parse(r.body);
return Array.isArray(body) ? body.length === 100 : false;
} catch (error) {
console.error('Error parsing response body: ', error);
return false;
}
},
});
}
@@ -0,0 +1,25 @@
{
"name": "data-table-node-benchmark",
"columns": [
{
"name": "firstName",
"type": "string"
},
{
"name": "age",
"type": "number"
},
{
"name": "birthDate",
"type": "date"
},
{
"name": "isActive",
"type": "boolean"
},
{
"name": "empty",
"type": "string"
}
]
}
@@ -0,0 +1,213 @@
{
"createdAt": "2024-09-04T07:18:29.011Z",
"updatedAt": "2024-09-04T07:27:58.000Z",
"id": "rUXzWNGsUDUmgaFS",
"name": "HTTP Request",
"active": false,
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "benchmark-http-node",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [-60, 20],
"id": "f11378b4-5f28-4a6c-9332-5878342cd3cf",
"name": "Webhook",
"webhookId": "c40014cc-4d64-4fcf-8c13-9e94b6792756"
},
{
"parameters": {
"respondWith": "allIncomingItems",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [1060, 20],
"id": "f42552c7-9c6e-4616-b9d5-ac79445ef4ed",
"name": "Respond to Webhook"
},
{
"parameters": {
"url": "http://mockapi:8080/users/clair.bahringer/received_events/public",
"options": {
"response": {
"response": {
"fullResponse": true
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [300, -180],
"id": "20de816e-0fbe-4e28-bc53-f508a2dda117",
"name": "Mock public received events"
},
{
"parameters": {
"url": "http://mockapi:8080/repos/udke6pujoywnagxkcvab2riw23khzn2tibo2vincws32qexb50ey7h97d42vnzyol0rxypgsg4pomsf7sgnmdaihstljw8edcijrwmy7mfi76yif19c4/47i31dh737el215j62ts2f2782nw3ss26rul3s8jw13u3vu0xm349a5hyay5asmwnlnf7nx8p9h4g62so6s1cis7xv9puj5j98t4m980sbe2455fn1obccjl/events",
"options": {
"response": {
"response": {
"fullResponse": true
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [300, 20],
"id": "083e02b3-a257-49a8-8f7d-42222cb9194c",
"name": "Mock repository events"
},
{
"parameters": {
"url": "http://mockapi:8080/orgs/g02pp066qoyithcjevhd6m1wfii3c4x51k39n9apybljhx69/events",
"options": {
"response": {
"response": {
"fullResponse": true
}
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [300, 220],
"id": "f4c3b5d2-0257-4883-a585-ade4c3a1082c",
"name": "Mock organization events"
},
{
"parameters": {
"numberInputs": 3
},
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [600, 20],
"id": "273985b7-b0ae-4cde-bbe9-7b3e4b29fe61",
"name": "Merge"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "89608adb-f487-416f-a7d8-3ebb1f7b50e5",
"name": "statusCode",
"value": "={{ $json.statusCode }}",
"type": "number"
}
]
},
"options": {}
},
"id": "231275a7-44e7-47bb-8ccf-fe62dc48356b",
"name": "Select statusCode",
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [820, 20]
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Mock public received events",
"type": "main",
"index": 0
},
{
"node": "Mock repository events",
"type": "main",
"index": 0
},
{
"node": "Mock organization events",
"type": "main",
"index": 0
}
]
]
},
"Mock public received events": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Mock repository events": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"Mock organization events": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 2
}
]
]
},
"Merge": {
"main": [
[
{
"node": "Select statusCode",
"type": "main",
"index": 0
}
]
]
},
"Select statusCode": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
}
},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": null,
"pinData": {
"Webhook": [
{
"json": {
"headers": { "host": "localhost:5678", "user-agent": "curl/8.6.0", "accept": "*/*" },
"params": {},
"query": {},
"body": {},
"webhookUrl": "http://localhost:5678/webhook-test/benchmark-http-node",
"executionMode": "test"
}
}
]
},
"versionId": "9fa91e54-e73a-4a34-b781-d64f2b02f333",
"triggerCount": 0,
"tags": []
}
@@ -0,0 +1,7 @@
{
"$schema": "../scenario.schema.json",
"name": "HttpNode",
"description": "Webhook -> 3x HTTP request to a mock API -> Merge -> Respond to Webhook. Requires a mock API running at http://mockapi:8080",
"scenarioData": { "workflowFiles": ["http-node.json"] },
"scriptPath": "http-node.script.js"
}
@@ -0,0 +1,30 @@
import http from 'k6/http';
import { check } from 'k6';
const apiBaseUrl = __ENV.API_BASE_URL;
export default function () {
const res = http.post(`${apiBaseUrl}/webhook/benchmark-http-node`);
if (res.status !== 200) {
console.error(
`Invalid response. Received status ${res.status}. Body: ${JSON.stringify(res.body)}`,
);
}
check(res, {
'is status 200': (r) => r.status === 200,
'http requests were OK': (r) => {
if (r.status !== 200) return false;
try {
// Response body is an array of the request status codes made with HttpNodes
const body = JSON.parse(r.body);
return Array.isArray(body) ? body.every((request) => request.statusCode === 200) : false;
} catch (error) {
console.error('Error parsing response body: ', error);
return false;
}
},
});
}
@@ -0,0 +1,96 @@
{
"createdAt": "2024-08-06T12:19:51.268Z",
"updatedAt": "2024-08-06T12:20:45.000Z",
"name": "JS Code Node",
"active": true,
"nodes": [
{
"parameters": {
"respondWith": "allIncomingItems",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [1280, 460],
"id": "0067e317-09b8-478a-8c50-e19b4c9e294c",
"name": "Respond to Webhook"
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Add new field\n$input.item.json.age = 10 + Math.floor(Math.random() * 30);\n// Mutate existing field\n$input.item.json.password = $input.item.json.password.split('').map(() => '*').join(\"\")\n// Remove field\ndelete $input.item.json.lastname\n// New object field\nconst emailParts = $input.item.json.email.split(\"@\")\n$input.item.json.emailData = {\n user: emailParts[0],\n domain: emailParts[1]\n}\n\nreturn $input.item;"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [1040, 460],
"id": "56d751c0-0d30-43c3-89fa-bebf3a9d436f",
"name": "OnceForEachItemJSCode"
},
{
"parameters": {
"httpMethod": "POST",
"path": "code-node-benchmark",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [580, 460],
"id": "417d749d-156c-4ffe-86ea-336f702dc5da",
"name": "Webhook",
"webhookId": "34ca1895-ccf4-4a4a-8bb8-a042f5edb567"
},
{
"parameters": {
"jsCode": "const digits = '0123456789';\nconst uppercaseLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst lowercaseLetters = uppercaseLetters.toLowerCase();\nconst alphabet = [digits, uppercaseLetters, lowercaseLetters].join('').split('')\n\nconst randomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;\nconst randomItem = (arr) => arr.at(randomInt(0, arr.length - 1))\nconst randomString = (len) => Array.from({ length: len }).map(() => randomItem(alphabet)).join('')\n\nconst randomUid = () => [8,4,4,4,8].map(len => randomString(len)).join(\"-\")\nconst randomEmail = () => `${randomString(8)}@${randomString(10)}.com`\n\nconst randomPerson = () => ({\n uid: randomUid(),\n email: randomEmail(),\n firstname: randomString(5),\n lastname: randomString(12),\n password: randomString(10)\n})\n\nreturn Array.from({ length: 100 }).map(() => ({\n json: randomPerson()\n}))"
},
"id": "c30db155-73ca-48b9-8860-c3fe7a0926fb",
"name": "Code",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [820, 460]
}
],
"connections": {
"OnceForEachItemJSCode": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Webhook": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
},
"Code": {
"main": [
[
{
"node": "OnceForEachItemJSCode",
"type": "main",
"index": 0
}
]
]
}
},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": { "templateCredsSetupCompleted": true, "responseMode": "lastNode", "options": {} },
"pinData": {},
"versionId": "840a38a1-ba37-433d-9f20-de73f5131a2b",
"triggerCount": 1,
"tags": []
}
@@ -0,0 +1,7 @@
{
"$schema": "../scenario.schema.json",
"name": "CodeNodeJs",
"description": "A JS Code Node that first generates 100 items and then runs once for each item and adds, modifies and removes properties. The data is returned with RespondToWebhook Node.",
"scenarioData": { "workflowFiles": ["js-code-node.json"] },
"scriptPath": "js-code-node.script.js"
}
@@ -0,0 +1,29 @@
import http from 'k6/http';
import { check } from 'k6';
const apiBaseUrl = __ENV.API_BASE_URL;
export default function () {
const res = http.post(`${apiBaseUrl}/webhook/code-node-benchmark`, {});
if (res.status !== 200) {
console.error(
`Invalid response. Received status ${res.status}. Body: ${JSON.stringify(res.body)}`,
);
}
check(res, {
'is status 200': (r) => r.status === 200,
'has items in response': (r) => {
if (r.status !== 200) return false;
try {
const body = JSON.parse(r.body);
return Array.isArray(body) ? body.length === 100 : false;
} catch (error) {
console.error('Error parsing response body: ', error);
return false;
}
},
});
}
@@ -0,0 +1,20 @@
{
"$schema": "../scenario.schema.json",
"name": "MultipleWebhooks",
"description": "10 simple webhooks that respond with a 200 status code",
"scenarioData": {
"workflowFiles": [
"multiple-webhooks1.json",
"multiple-webhooks2.json",
"multiple-webhooks3.json",
"multiple-webhooks4.json",
"multiple-webhooks5.json",
"multiple-webhooks6.json",
"multiple-webhooks7.json",
"multiple-webhooks8.json",
"multiple-webhooks9.json",
"multiple-webhooks10.json"
]
},
"scriptPath": "multiple-webhooks.script.js"
}
@@ -0,0 +1,19 @@
import http from 'k6/http';
import { check } from 'k6';
const apiBaseUrl = __ENV.API_BASE_URL;
export default function () {
const urls = Array(10)
.fill()
.map((_, i) => `${apiBaseUrl}/webhook/multiple-webhook${i + 1}`);
const res = http.batch(urls);
for (let i = 0; i < res.length; i++) {
// Check if the response status is 200
check(res[i], {
'is status 200': (r) => r.status === 200,
});
}
}
@@ -0,0 +1,25 @@
{
"createdAt": "2024-08-06T12:19:51.268Z",
"updatedAt": "2024-08-06T12:20:45.000Z",
"name": "Multiple Webhook 1",
"active": true,
"nodes": [
{
"parameters": { "path": "multiple-webhook1", "options": {} },
"id": "b239bc6c-ea40-438d-bb14-5bce03599685",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [760, 400],
"webhookId": "14226baf-ea56-43d7-bc0d-eea841746441"
}
],
"connections": {},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": { "templateCredsSetupCompleted": true, "responseMode": "lastNode", "options": {} },
"pinData": {},
"versionId": "0322386c-ec84-4d38-b895-c206b574f31c",
"triggerCount": 1,
"tags": []
}
@@ -0,0 +1,25 @@
{
"createdAt": "2024-08-06T12:19:51.268Z",
"updatedAt": "2024-08-06T12:20:45.000Z",
"name": "Multiple Webhook 10",
"active": true,
"nodes": [
{
"parameters": { "path": "multiple-webhook10", "options": {} },
"id": "34ac4500-9a29-4f4f-a604-134aa2cb2889",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [760, 400],
"webhookId": "47fe25ac-1376-4ee7-b9de-3fff1d49281c"
}
],
"connections": {},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": { "templateCredsSetupCompleted": true, "responseMode": "lastNode", "options": {} },
"pinData": {},
"versionId": "106d4d2c-49c0-45b8-8421-99cc0c8b1589",
"triggerCount": 1,
"tags": []
}
@@ -0,0 +1,25 @@
{
"createdAt": "2024-08-06T12:19:51.268Z",
"updatedAt": "2024-08-06T12:20:45.000Z",
"name": "Multiple Webhook 2",
"active": true,
"nodes": [
{
"parameters": { "path": "multiple-webhook2", "options": {} },
"id": "c44ce610-086c-45a6-b347-c7b5df5365ed",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [760, 400],
"webhookId": "edc1994b-7cde-4aed-b077-fbc7f21b0f48"
}
],
"connections": {},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": { "templateCredsSetupCompleted": true, "responseMode": "lastNode", "options": {} },
"pinData": {},
"versionId": "b4579dbf-d9c5-4b57-8e1f-883d91e8726b",
"triggerCount": 1,
"tags": []
}
@@ -0,0 +1,25 @@
{
"createdAt": "2024-08-06T12:19:51.268Z",
"updatedAt": "2024-08-06T12:20:45.000Z",
"name": "Multiple Webhook 3",
"active": true,
"nodes": [
{
"parameters": { "path": "multiple-webhook3", "options": {} },
"id": "34ac4500-9a29-4f4f-a604-134aa2cb2889",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [760, 400],
"webhookId": "47fe25ac-1376-4ee7-b9de-3fff1d49281c"
}
],
"connections": {},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": { "templateCredsSetupCompleted": true, "responseMode": "lastNode", "options": {} },
"pinData": {},
"versionId": "106d4d2c-49c0-45b8-8421-99cc0c8b1589",
"triggerCount": 1,
"tags": []
}
@@ -0,0 +1,25 @@
{
"createdAt": "2024-08-06T12:19:51.268Z",
"updatedAt": "2024-08-06T12:20:45.000Z",
"name": "Multiple Webhook 4",
"active": true,
"nodes": [
{
"parameters": { "path": "multiple-webhook4", "options": {} },
"id": "34ac4500-9a29-4f4f-a604-134aa2cb2889",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [760, 400],
"webhookId": "47fe25ac-1376-4ee7-b9de-3fff1d49281c"
}
],
"connections": {},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": { "templateCredsSetupCompleted": true, "responseMode": "lastNode", "options": {} },
"pinData": {},
"versionId": "106d4d2c-49c0-45b8-8421-99cc0c8b1589",
"triggerCount": 1,
"tags": []
}
@@ -0,0 +1,25 @@
{
"createdAt": "2024-08-06T12:19:51.268Z",
"updatedAt": "2024-08-06T12:20:45.000Z",
"name": "Multiple Webhook 5",
"active": true,
"nodes": [
{
"parameters": { "path": "multiple-webhook5", "options": {} },
"id": "34ac4500-9a29-4f4f-a604-134aa2cb2889",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [760, 400],
"webhookId": "47fe25ac-1376-4ee7-b9de-3fff1d49281c"
}
],
"connections": {},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": { "templateCredsSetupCompleted": true, "responseMode": "lastNode", "options": {} },
"pinData": {},
"versionId": "106d4d2c-49c0-45b8-8421-99cc0c8b1589",
"triggerCount": 1,
"tags": []
}
@@ -0,0 +1,25 @@
{
"createdAt": "2024-08-06T12:19:51.268Z",
"updatedAt": "2024-08-06T12:20:45.000Z",
"name": "Multiple Webhook 6",
"active": true,
"nodes": [
{
"parameters": { "path": "multiple-webhook6", "options": {} },
"id": "34ac4500-9a29-4f4f-a604-134aa2cb2889",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [760, 400],
"webhookId": "47fe25ac-1376-4ee7-b9de-3fff1d49281c"
}
],
"connections": {},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": { "templateCredsSetupCompleted": true, "responseMode": "lastNode", "options": {} },
"pinData": {},
"versionId": "106d4d2c-49c0-45b8-8421-99cc0c8b1589",
"triggerCount": 1,
"tags": []
}
@@ -0,0 +1,25 @@
{
"createdAt": "2024-08-06T12:19:51.268Z",
"updatedAt": "2024-08-06T12:20:45.000Z",
"name": "Multiple Webhook 7",
"active": true,
"nodes": [
{
"parameters": { "path": "multiple-webhook7", "options": {} },
"id": "34ac4500-9a29-4f4f-a604-134aa2cb2889",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [760, 400],
"webhookId": "47fe25ac-1376-4ee7-b9de-3fff1d49281c"
}
],
"connections": {},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": { "templateCredsSetupCompleted": true, "responseMode": "lastNode", "options": {} },
"pinData": {},
"versionId": "106d4d2c-49c0-45b8-8421-99cc0c8b1589",
"triggerCount": 1,
"tags": []
}
@@ -0,0 +1,25 @@
{
"createdAt": "2024-08-06T12:19:51.268Z",
"updatedAt": "2024-08-06T12:20:45.000Z",
"name": "Multiple Webhook 8",
"active": true,
"nodes": [
{
"parameters": { "path": "multiple-webhook8", "options": {} },
"id": "34ac4500-9a29-4f4f-a604-134aa2cb2889",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [760, 400],
"webhookId": "47fe25ac-1376-4ee7-b9de-3fff1d49281c"
}
],
"connections": {},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": { "templateCredsSetupCompleted": true, "responseMode": "lastNode", "options": {} },
"pinData": {},
"versionId": "106d4d2c-49c0-45b8-8421-99cc0c8b1589",
"triggerCount": 1,
"tags": []
}
@@ -0,0 +1,25 @@
{
"createdAt": "2024-08-06T12:19:51.268Z",
"updatedAt": "2024-08-06T12:20:45.000Z",
"name": "Multiple Webhook 9",
"active": true,
"nodes": [
{
"parameters": { "path": "multiple-webhook9", "options": {} },
"id": "34ac4500-9a29-4f4f-a604-134aa2cb2889",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [760, 400],
"webhookId": "47fe25ac-1376-4ee7-b9de-3fff1d49281c"
}
],
"connections": {},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": { "templateCredsSetupCompleted": true, "responseMode": "lastNode", "options": {} },
"pinData": {},
"versionId": "106d4d2c-49c0-45b8-8421-99cc0c8b1589",
"triggerCount": 1,
"tags": []
}
@@ -0,0 +1,98 @@
{
"createdAt": "2024-08-06T12:19:51.268Z",
"updatedAt": "2024-08-06T12:20:45.000Z",
"name": "Python Code Node",
"active": true,
"nodes": [
{
"parameters": {
"respondWith": "allIncomingItems",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [1280, 460],
"id": "0067e317-09b8-478a-8c50-e19b4c9e294c",
"name": "Respond to Webhook"
},
{
"parameters": {
"language": "pythonNative",
"mode": "runOnceForEachItem",
"pythonCode": "def pseudo_random(seed_str, max_val):\n return hash(seed_str) % max_val\n\n# Add new field\n_item['json']['age'] = 10 + pseudo_random(str(_item['json']['email']), 30)\n\n# Mutate existing field\n_item['json']['password'] = '*' * len(_item['json']['password'])\n\n# Remove field\nif 'lastname' in _item['json']:\n del _item['json']['lastname']\n\n# New object field\nemail_parts = _item['json']['email'].split('@')\n_item['json']['emailData'] = {\n 'user': email_parts[0],\n 'domain': email_parts[1]\n}\n\nreturn _item"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [1040, 460],
"id": "56d751c0-0d30-43c3-89fa-bebf3a9d436f",
"name": "OnceForEachItemPythonCode"
},
{
"parameters": {
"httpMethod": "POST",
"path": "py-code-node-benchmark",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [580, 460],
"id": "417d749d-156c-4ffe-86ea-336f702dc5da",
"name": "Webhook",
"webhookId": "34ca1895-ccf4-4a4a-8bb8-a042f5edb567"
},
{
"parameters": {
"language": "pythonNative",
"pythonCode": "def pseudo_random_string(length):\n characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'\n result = ''\n seed = hash(str(length)) % 1000\n for i in range(length):\n index = (hash(str(seed + i)) % len(characters))\n result += characters[index]\n seed = (seed * 31 + i) % 1000\n return result\n\ndef random_uid():\n lengths = [8, 4, 4, 4, 8]\n parts = [pseudo_random_string(length) for length in lengths]\n return '-'.join(parts)\n\ndef random_email():\n return f\"{pseudo_random_string(8)}@{pseudo_random_string(10)}.com\"\n\ndef random_person():\n return {\n 'uid': random_uid(),\n 'email': random_email(),\n 'firstname': pseudo_random_string(5),\n 'lastname': pseudo_random_string(12),\n 'password': pseudo_random_string(10)\n }\n\nreturn [{'json': random_person()} for _ in range(100)]"
},
"id": "c30db155-73ca-48b9-8860-c3fe7a0926fb",
"name": "Code",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [820, 460]
}
],
"connections": {
"OnceForEachItemPythonCode": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Webhook": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
},
"Code": {
"main": [
[
{
"node": "OnceForEachItemPythonCode",
"type": "main",
"index": 0
}
]
]
}
},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": { "templateCredsSetupCompleted": true, "responseMode": "lastNode", "options": {} },
"pinData": {},
"versionId": "840a38a1-ba37-433d-9f20-de73f5131a2b",
"triggerCount": 1,
"tags": []
}
@@ -0,0 +1,7 @@
{
"$schema": "../scenario.schema.json",
"name": "CodeNodePython",
"description": "A Python Code Node that first generates 100 items and then runs once for each item and adds, modifies and removes properties. The data is returned with RespondToWebhook Node.",
"scenarioData": { "workflowFiles": ["py-code-node.json"] },
"scriptPath": "py-code-node.script.js"
}
@@ -0,0 +1,29 @@
import http from 'k6/http';
import { check } from 'k6';
const apiBaseUrl = __ENV.API_BASE_URL;
export default function () {
const res = http.post(`${apiBaseUrl}/webhook/py-code-node-benchmark`, {});
if (res.status !== 200) {
console.error(
`Invalid response. Received status ${res.status}. Body: ${JSON.stringify(res.body)}`,
);
}
check(res, {
'is status 200': (r) => r.status === 200,
'has items in response': (r) => {
if (r.status !== 200) return false;
try {
const body = JSON.parse(r.body);
return Array.isArray(body) ? body.length === 100 : false;
} catch (error) {
console.error('Error parsing response body: ', error);
return false;
}
},
});
}
@@ -0,0 +1,51 @@
{
"definitions": {
"ScenarioData": {
"type": "object",
"properties": {
"workflowFiles": {
"type": "array",
"items": {
"type": "string"
}
},
"credentialFiles": {
"type": "array",
"items": {
"type": "string"
}
},
"dataTableFile": {
"type": "string"
}
},
"required": [],
"additionalProperties": false
}
},
"type": "object",
"properties": {
"$schema": {
"type": "string",
"description": "The JSON schema to validate this file"
},
"name": {
"type": "string",
"description": "The name of the scenario"
},
"description": {
"type": "string",
"description": "A longer description of the scenario"
},
"scriptPath": {
"type": "string",
"description": "Relative path to the k6 test script"
},
"scenarioData": {
"$ref": "#/definitions/ScenarioData",
"description": "Data to import before running the scenario"
}
},
"required": ["name", "description", "scriptPath", "scenarioData"],
"additionalProperties": false
}
@@ -0,0 +1,91 @@
{
"createdAt": "2024-09-03T11:30:26.333Z",
"updatedAt": "2024-09-03T11:42:52.000Z",
"name": "Set Node Expressions",
"active": false,
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "set-expressions-benchmark",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [40, 0],
"id": "5babc228-2b89-48cb-8337-28416e867874",
"name": "Webhook",
"webhookId": "f6f1750d-b734-496f-afe8-26e8e393ca87"
},
{
"parameters": { "respondWith": "allIncomingItems", "options": {} },
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [640, 0],
"id": "4146a3fb-403c-4cfc-9d38-8af4d16a8440",
"name": "Respond to Webhook"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "48c46098-f411-41f7-8f0a-1da372340a4e",
"name": "oneToOneCopy",
"value": "={{ $json.headers.host }}",
"type": "string"
},
{
"id": "5d90808b-1c1a-4065-ac51-6d61bd03e564",
"name": "={{ $json.headers['user-agent'].slice(0, 4) }}",
"value": "Set key with expression",
"type": "string"
},
{
"id": "8a74ac24-1f43-43ba-969d-87bfd2f401ce",
"name": "Multiple variables",
"value": "={{ $json.executionMode + ' ' + $json.webhookUrl }}",
"type": "string"
},
{
"id": "93eba201-79d9-4305-a246-f9c8ec50ebab",
"name": "Static value",
"value": 42,
"type": "number"
},
{
"id": "0470a712-c795-44ab-9dcc-05a3f67698bb",
"name": "Object",
"value": "={{ $json.headers }}",
"type": "object"
},
{
"id": "eb671167-da14-4b55-8eea-31ab7bedae10",
"name": "Array",
"value": "={{ Object.values($json.headers) }}",
"type": "array"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [360, 0],
"id": "0cb5e82d-f61e-4d91-8fa9-365e382a4d75",
"name": "Edit Fields"
}
],
"connections": {
"Webhook": { "main": [[{ "node": "Edit Fields", "type": "main", "index": 0 }]] },
"Edit Fields": { "main": [[{ "node": "Respond to Webhook", "type": "main", "index": 0 }]] }
},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": null,
"pinData": {},
"versionId": "04fd543e-3923-4092-8c2b-2b4262ccbb38",
"triggerCount": 0,
"tags": []
}
@@ -0,0 +1,7 @@
{
"$schema": "../scenario.schema.json",
"name": "SetNodeExpressions",
"description": "Expressions in a Set node",
"scenarioData": { "workflowFiles": ["set-node-expressions.json"] },
"scriptPath": "set-node-expressions.script.js"
}
@@ -0,0 +1,18 @@
import http from 'k6/http';
import { check } from 'k6';
const apiBaseUrl = __ENV.API_BASE_URL;
export default function () {
const res = http.post(`${apiBaseUrl}/webhook/set-expressions-benchmark`, {});
if (res.status !== 200) {
console.error(
`Invalid response. Received status ${res.status}. Body: ${JSON.stringify(res.body)}`,
);
}
check(res, {
'is status 200': (r) => r.status === 200,
});
}
@@ -0,0 +1,25 @@
{
"createdAt": "2024-08-06T12:19:51.268Z",
"updatedAt": "2024-08-06T12:20:45.000Z",
"name": "Single Webhook",
"active": true,
"nodes": [
{
"parameters": { "path": "single-webhook", "options": {} },
"id": "7587ab0e-cc15-424f-83c0-c887a0eb97fb",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [760, 400],
"webhookId": "fa563fc2-c73f-4631-99a1-39c16f1f858f"
}
],
"connections": {},
"settings": { "executionOrder": "v1" },
"staticData": null,
"meta": { "templateCredsSetupCompleted": true, "responseMode": "lastNode", "options": {} },
"pinData": {},
"versionId": "840a38a1-ba37-433d-9f20-de73f5131a2b",
"triggerCount": 1,
"tags": []
}
@@ -0,0 +1,7 @@
{
"$schema": "../scenario.schema.json",
"name": "SingleWebhook",
"description": "A single webhook trigger that responds with a 200 status code",
"scenarioData": { "workflowFiles": ["single-webhook.json"] },
"scriptPath": "single-webhook.script.js"
}
@@ -0,0 +1,18 @@
import http from 'k6/http';
import { check } from 'k6';
const apiBaseUrl = __ENV.API_BASE_URL;
export default function () {
const res = http.get(`${apiBaseUrl}/webhook/single-webhook`);
if (res.status !== 200) {
console.error(
`Invalid response. Received status ${res.status}. Body: ${JSON.stringify(res.body)}`,
);
}
check(res, {
'is status 200': (r) => r.status === 200,
});
}