@atom8n/n8n-benchmark 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/Dockerfile +63 -0
  3. package/README.md +122 -0
  4. package/bin/n8n-benchmark +13 -0
  5. package/biome.jsonc +7 -0
  6. package/dist/build.tsbuildinfo +1 -0
  7. package/dist/commands/list.d.ts +8 -0
  8. package/dist/commands/list.js +23 -0
  9. package/dist/commands/list.js.map +1 -0
  10. package/dist/commands/run.d.ts +24 -0
  11. package/dist/commands/run.js +128 -0
  12. package/dist/commands/run.js.map +1 -0
  13. package/dist/config/common-flags.d.ts +1 -0
  14. package/dist/config/common-flags.js +9 -0
  15. package/dist/config/common-flags.js.map +1 -0
  16. package/dist/n8n-api-client/authenticated-n8n-api-client.d.ts +15 -0
  17. package/dist/n8n-api-client/authenticated-n8n-api-client.js +67 -0
  18. package/dist/n8n-api-client/authenticated-n8n-api-client.js.map +1 -0
  19. package/dist/n8n-api-client/credentials-api-client.d.ts +9 -0
  20. package/dist/n8n-api-client/credentials-api-client.js +24 -0
  21. package/dist/n8n-api-client/credentials-api-client.js.map +1 -0
  22. package/dist/n8n-api-client/data-table-api-client.d.ts +9 -0
  23. package/dist/n8n-api-client/data-table-api-client.js +23 -0
  24. package/dist/n8n-api-client/data-table-api-client.js.map +1 -0
  25. package/dist/n8n-api-client/n8n-api-client.d.ts +13 -0
  26. package/dist/n8n-api-client/n8n-api-client.js +82 -0
  27. package/dist/n8n-api-client/n8n-api-client.js.map +1 -0
  28. package/dist/n8n-api-client/n8n-api-client.types.d.ts +21 -0
  29. package/dist/n8n-api-client/n8n-api-client.types.js +3 -0
  30. package/dist/n8n-api-client/n8n-api-client.types.js.map +1 -0
  31. package/dist/n8n-api-client/project-api-client.d.ts +6 -0
  32. package/dist/n8n-api-client/project-api-client.js +14 -0
  33. package/dist/n8n-api-client/project-api-client.js.map +1 -0
  34. package/dist/n8n-api-client/workflows-api-client.d.ts +11 -0
  35. package/dist/n8n-api-client/workflows-api-client.js +30 -0
  36. package/dist/n8n-api-client/workflows-api-client.js.map +1 -0
  37. package/dist/scenario/scenario-data-loader.d.ts +13 -0
  38. package/dist/scenario/scenario-data-loader.js +84 -0
  39. package/dist/scenario/scenario-data-loader.js.map +1 -0
  40. package/dist/scenario/scenario-loader.d.ts +7 -0
  41. package/dist/scenario/scenario-loader.js +101 -0
  42. package/dist/scenario/scenario-loader.js.map +1 -0
  43. package/dist/test-execution/app-metrics-poller.d.ts +13 -0
  44. package/dist/test-execution/app-metrics-poller.js +54 -0
  45. package/dist/test-execution/app-metrics-poller.js.map +1 -0
  46. package/dist/test-execution/k6-executor.d.ts +33 -0
  47. package/dist/test-execution/k6-executor.js +120 -0
  48. package/dist/test-execution/k6-executor.js.map +1 -0
  49. package/dist/test-execution/k6-summary.d.ts +82 -0
  50. package/dist/test-execution/k6-summary.js +2 -0
  51. package/dist/test-execution/k6-summary.js.map +1 -0
  52. package/dist/test-execution/prometheus-metrics-parser.d.ts +9 -0
  53. package/dist/test-execution/prometheus-metrics-parser.js +44 -0
  54. package/dist/test-execution/prometheus-metrics-parser.js.map +1 -0
  55. package/dist/test-execution/scenario-data-importer.d.ts +21 -0
  56. package/dist/test-execution/scenario-data-importer.js +108 -0
  57. package/dist/test-execution/scenario-data-importer.js.map +1 -0
  58. package/dist/test-execution/scenario-runner.d.ts +18 -0
  59. package/dist/test-execution/scenario-runner.js +46 -0
  60. package/dist/test-execution/scenario-runner.js.map +1 -0
  61. package/dist/test-execution/test-report.d.ts +56 -0
  62. package/dist/test-execution/test-report.js +65 -0
  63. package/dist/test-execution/test-report.js.map +1 -0
  64. package/dist/types/scenario.d.ts +16 -0
  65. package/dist/types/scenario.js +3 -0
  66. package/dist/types/scenario.js.map +1 -0
  67. package/eslint.config.mjs +22 -0
  68. package/infra/.terraform.lock.hcl +60 -0
  69. package/infra/benchmark-env.tf +54 -0
  70. package/infra/modules/benchmark-vm/output.tf +11 -0
  71. package/infra/modules/benchmark-vm/vars.tf +29 -0
  72. package/infra/modules/benchmark-vm/vm.tf +126 -0
  73. package/infra/output.tf +16 -0
  74. package/infra/providers.tf +23 -0
  75. package/infra/vars.tf +34 -0
  76. package/package.json +55 -0
  77. package/scenarios/binary-data/binary-data.json +67 -0
  78. package/scenarios/binary-data/binary-data.manifest.json +7 -0
  79. package/scenarios/binary-data/binary-data.script.js +29 -0
  80. package/scenarios/credential-http-node/credential-bearer.json +8 -0
  81. package/scenarios/credential-http-node/credential-http-node.json +241 -0
  82. package/scenarios/credential-http-node/credential-http-node.manifest.json +10 -0
  83. package/scenarios/credential-http-node/credential-http-node.script.js +30 -0
  84. package/scenarios/data-table-node/data-table-node.json +168 -0
  85. package/scenarios/data-table-node/data-table-node.manifest.json +10 -0
  86. package/scenarios/data-table-node/data-table-node.script.js +38 -0
  87. package/scenarios/data-table-node/data-table.json +25 -0
  88. package/scenarios/http-node/http-node.json +213 -0
  89. package/scenarios/http-node/http-node.manifest.json +7 -0
  90. package/scenarios/http-node/http-node.script.js +30 -0
  91. package/scenarios/js-code-node/js-code-node.json +96 -0
  92. package/scenarios/js-code-node/js-code-node.manifest.json +7 -0
  93. package/scenarios/js-code-node/js-code-node.script.js +29 -0
  94. package/scenarios/multiple-webhooks/multiple-webhooks.manifest.json +20 -0
  95. package/scenarios/multiple-webhooks/multiple-webhooks.script.js +19 -0
  96. package/scenarios/multiple-webhooks/multiple-webhooks1.json +25 -0
  97. package/scenarios/multiple-webhooks/multiple-webhooks10.json +25 -0
  98. package/scenarios/multiple-webhooks/multiple-webhooks2.json +25 -0
  99. package/scenarios/multiple-webhooks/multiple-webhooks3.json +25 -0
  100. package/scenarios/multiple-webhooks/multiple-webhooks4.json +25 -0
  101. package/scenarios/multiple-webhooks/multiple-webhooks5.json +25 -0
  102. package/scenarios/multiple-webhooks/multiple-webhooks6.json +25 -0
  103. package/scenarios/multiple-webhooks/multiple-webhooks7.json +25 -0
  104. package/scenarios/multiple-webhooks/multiple-webhooks8.json +25 -0
  105. package/scenarios/multiple-webhooks/multiple-webhooks9.json +25 -0
  106. package/scenarios/py-code-node/py-code-node.json +98 -0
  107. package/scenarios/py-code-node/py-code-node.manifest.json +7 -0
  108. package/scenarios/py-code-node/py-code-node.script.js +29 -0
  109. package/scenarios/scenario.schema.json +51 -0
  110. package/scenarios/set-node-expressions/set-node-expressions.json +91 -0
  111. package/scenarios/set-node-expressions/set-node-expressions.manifest.json +7 -0
  112. package/scenarios/set-node-expressions/set-node-expressions.script.js +18 -0
  113. package/scenarios/single-webhook/single-webhook.json +25 -0
  114. package/scenarios/single-webhook/single-webhook.manifest.json +7 -0
  115. package/scenarios/single-webhook/single-webhook.script.js +18 -0
  116. package/scripts/bootstrap.sh +63 -0
  117. package/scripts/clients/docker-compose-client.mjs +45 -0
  118. package/scripts/clients/ssh-client.mjs +37 -0
  119. package/scripts/clients/terraform-client.mjs +71 -0
  120. package/scripts/destroy-cloud-env.mjs +86 -0
  121. package/scripts/mock-api/mappings/mockApiData.json +92110 -0
  122. package/scripts/n8n-setups/postgres/docker-compose.yml +76 -0
  123. package/scripts/n8n-setups/postgres/setup.mjs +15 -0
  124. package/scripts/n8n-setups/scaling-multi-main/docker-compose.yml +230 -0
  125. package/scripts/n8n-setups/scaling-multi-main/nginx.conf +24 -0
  126. package/scripts/n8n-setups/scaling-multi-main/setup.mjs +15 -0
  127. package/scripts/n8n-setups/scaling-single-main/docker-compose.yml +174 -0
  128. package/scripts/n8n-setups/scaling-single-main/setup.mjs +15 -0
  129. package/scripts/n8n-setups/sqlite/docker-compose.yml +55 -0
  130. package/scripts/n8n-setups/sqlite/setup.mjs +15 -0
  131. package/scripts/provision-cloud-env.mjs +36 -0
  132. package/scripts/run-for-n8n-setup.mjs +175 -0
  133. package/scripts/run-in-cloud.mjs +167 -0
  134. package/scripts/run-locally.mjs +73 -0
  135. package/scripts/run.mjs +192 -0
  136. package/scripts/utils/flags.mjs +20 -0
  137. package/src/commands/list.ts +26 -0
  138. package/src/commands/run.ts +140 -0
  139. package/src/config/common-flags.ts +6 -0
  140. package/src/n8n-api-client/authenticated-n8n-api-client.ts +88 -0
  141. package/src/n8n-api-client/credentials-api-client.ts +28 -0
  142. package/src/n8n-api-client/data-table-api-client.ts +30 -0
  143. package/src/n8n-api-client/n8n-api-client.ts +85 -0
  144. package/src/n8n-api-client/n8n-api-client.types.ts +27 -0
  145. package/src/n8n-api-client/project-api-client.ts +11 -0
  146. package/src/n8n-api-client/workflows-api-client.ts +38 -0
  147. package/src/scenario/scenario-data-loader.ts +75 -0
  148. package/src/scenario/scenario-loader.ts +90 -0
  149. package/src/test-execution/app-metrics-poller.ts +81 -0
  150. package/src/test-execution/k6-executor.ts +192 -0
  151. package/src/test-execution/k6-summary.ts +255 -0
  152. package/src/test-execution/prometheus-metrics-parser.ts +63 -0
  153. package/src/test-execution/scenario-data-importer.ts +165 -0
  154. package/src/test-execution/scenario-runner.ts +76 -0
  155. package/src/test-execution/test-report.ts +152 -0
  156. package/src/types/scenario.ts +33 -0
  157. package/tsconfig.build.json +9 -0
  158. package/tsconfig.json +14 -0
@@ -0,0 +1,76 @@
1
+ services:
2
+ mockapi:
3
+ image: wiremock/wiremock:3.9.1
4
+ ports:
5
+ - '8088:8080'
6
+ volumes:
7
+ - ${MOCK_API_DATA_PATH}/mappings:/home/wiremock/mappings
8
+
9
+ postgres:
10
+ image: postgres:16.4
11
+ restart: always
12
+ user: root:root
13
+ environment:
14
+ - POSTGRES_DB=n8n
15
+ - POSTGRES_USER=postgres
16
+ - POSTGRES_PASSWORD=password
17
+ - PGDATA=/var/lib/postgresql/data/pgdata
18
+ volumes:
19
+ - ${RUN_DIR}/postgres:/var/lib/postgresql/data
20
+ healthcheck:
21
+ test: ['CMD-SHELL', 'pg_isready -U postgres']
22
+ interval: 5s
23
+ timeout: 5s
24
+ retries: 5
25
+
26
+ n8n:
27
+ image: ghcr.io/n8n-io/n8n:${N8N_VERSION:-latest}
28
+ user: root:root
29
+ environment:
30
+ - N8N_DIAGNOSTICS_ENABLED=false
31
+ - N8N_USER_FOLDER=/n8n
32
+ - DB_TYPE=postgresdb
33
+ - DB_POSTGRESDB_HOST=postgres
34
+ - DB_POSTGRESDB_PASSWORD=password
35
+ # Task Runner config
36
+ - N8N_RUNNERS_ENABLED=true
37
+ - N8N_RUNNERS_MODE=external
38
+ - N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
39
+ - N8N_RUNNERS_AUTH_TOKEN=test
40
+ - N8N_METRICS=true
41
+ ports:
42
+ - 5678:5678
43
+ volumes:
44
+ - ${RUN_DIR}/n8n:/n8n
45
+ depends_on:
46
+ postgres:
47
+ condition: service_healthy
48
+ mockapi:
49
+ condition: service_started
50
+ healthcheck:
51
+ test: ['CMD-SHELL', 'wget --spider -q http://n8n:5678/healthz || exit 1']
52
+ interval: 5s
53
+ timeout: 5s
54
+ retries: 10
55
+
56
+ runners:
57
+ image: ghcr.io/n8n-io/runners:${N8N_VERSION:-latest}
58
+ environment:
59
+ - N8N_RUNNERS_TASK_BROKER_URI=http://n8n:5679
60
+ - N8N_RUNNERS_AUTH_TOKEN=test
61
+ - NO_COLOR=1
62
+ depends_on:
63
+ n8n:
64
+ condition: service_healthy
65
+
66
+ benchmark:
67
+ image: ghcr.io/n8n-io/n8n-benchmark:${N8N_BENCHMARK_VERSION:-latest}
68
+ depends_on:
69
+ n8n:
70
+ condition: service_healthy
71
+ environment:
72
+ - N8N_BASE_URL=http://n8n:5678
73
+ - K6_API_TOKEN=${K6_API_TOKEN}
74
+ - BENCHMARK_RESULT_WEBHOOK_URL=${BENCHMARK_RESULT_WEBHOOK_URL}
75
+ - BENCHMARK_RESULT_WEBHOOK_AUTH_HEADER=${BENCHMARK_RESULT_WEBHOOK_AUTH_HEADER}
76
+ - COLLECT_APP_METRICS=true
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env zx
2
+
3
+ import path from 'path';
4
+ import { fs } from 'zx';
5
+
6
+ /**
7
+ * Creates the needed directories so the permissions get set correctly.
8
+ */
9
+ export function setup({ runDir }) {
10
+ const neededDirs = ['n8n', 'postgres'];
11
+
12
+ for (const dir of neededDirs) {
13
+ fs.ensureDirSync(path.join(runDir, dir));
14
+ }
15
+ }
@@ -0,0 +1,230 @@
1
+ services:
2
+ mockapi:
3
+ image: wiremock/wiremock:3.9.1
4
+ ports:
5
+ - '8088:8080'
6
+ volumes:
7
+ - ${MOCK_API_DATA_PATH}/mappings:/home/wiremock/mappings
8
+
9
+ redis:
10
+ image: redis:6.2.14-alpine
11
+ restart: always
12
+ ports:
13
+ - 6379:6379
14
+ healthcheck:
15
+ test: ['CMD', 'redis-cli', 'ping']
16
+ interval: 1s
17
+ timeout: 3s
18
+
19
+ postgres:
20
+ image: postgres:16.4
21
+ restart: always
22
+ environment:
23
+ - POSTGRES_DB=n8n
24
+ - POSTGRES_USER=postgres
25
+ - POSTGRES_PASSWORD=password
26
+ - PGDATA=/var/lib/postgresql/data/pgdata
27
+ volumes:
28
+ - ${RUN_DIR}/postgres:/var/lib/postgresql/data
29
+ healthcheck:
30
+ test: ['CMD-SHELL', 'pg_isready -U postgres']
31
+ interval: 5s
32
+ timeout: 5s
33
+ retries: 10
34
+
35
+ n8n_worker1:
36
+ image: ghcr.io/n8n-io/n8n:${N8N_VERSION:-latest}
37
+ environment:
38
+ - N8N_DIAGNOSTICS_ENABLED=false
39
+ - N8N_USER_FOLDER=/n8n/worker1
40
+ - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
41
+ - N8N_LICENSE_CERT=${N8N_LICENSE_CERT}
42
+ - N8N_LICENSE_ACTIVATION_KEY=${N8N_LICENSE_ACTIVATION_KEY}
43
+ - N8N_LICENSE_TENANT_ID=${N8N_LICENSE_TENANT_ID}
44
+ # Scaling mode config
45
+ - EXECUTIONS_MODE=queue
46
+ - QUEUE_BULL_REDIS_HOST=redis
47
+ - QUEUE_HEALTH_CHECK_ACTIVE=true
48
+ - N8N_CONCURRENCY_PRODUCTION_LIMIT=10
49
+ # DB config
50
+ - DB_TYPE=postgresdb
51
+ - DB_POSTGRESDB_HOST=postgres
52
+ - DB_POSTGRESDB_PASSWORD=password
53
+ # Task Runner config
54
+ - N8N_RUNNERS_ENABLED=true
55
+ - N8N_RUNNERS_MODE=external
56
+ - N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
57
+ - N8N_RUNNERS_AUTH_TOKEN=test
58
+ command: worker
59
+ volumes:
60
+ - ${RUN_DIR}/n8n-worker1:/n8n
61
+ depends_on:
62
+ postgres:
63
+ condition: service_healthy
64
+ redis:
65
+ condition: service_healthy
66
+ healthcheck:
67
+ test: ['CMD-SHELL', 'wget --spider -q http://localhost:5678/healthz || exit 1']
68
+ interval: 5s
69
+ timeout: 5s
70
+ retries: 10
71
+
72
+ n8n_worker1_runners:
73
+ image: ghcr.io/n8n-io/runners:${N8N_VERSION:-latest}
74
+ environment:
75
+ - N8N_RUNNERS_TASK_BROKER_URI=http://n8n_worker1:5679
76
+ - N8N_RUNNERS_AUTH_TOKEN=test
77
+ - NO_COLOR=1
78
+ depends_on:
79
+ n8n_worker1:
80
+ condition: service_healthy
81
+
82
+ n8n_worker2:
83
+ image: ghcr.io/n8n-io/n8n:${N8N_VERSION:-latest}
84
+ environment:
85
+ - N8N_DIAGNOSTICS_ENABLED=false
86
+ - N8N_USER_FOLDER=/n8n/worker2
87
+ - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
88
+ - N8N_LICENSE_CERT=${N8N_LICENSE_CERT}
89
+ - N8N_LICENSE_ACTIVATION_KEY=${N8N_LICENSE_ACTIVATION_KEY}
90
+ - N8N_LICENSE_TENANT_ID=${N8N_LICENSE_TENANT_ID}
91
+ # Scaling mode config
92
+ - EXECUTIONS_MODE=queue
93
+ - QUEUE_BULL_REDIS_HOST=redis
94
+ - QUEUE_HEALTH_CHECK_ACTIVE=true
95
+ - N8N_CONCURRENCY_PRODUCTION_LIMIT=10
96
+ # DB config
97
+ - DB_TYPE=postgresdb
98
+ - DB_POSTGRESDB_HOST=postgres
99
+ - DB_POSTGRESDB_PASSWORD=password
100
+ # Task Runner config
101
+ - N8N_RUNNERS_ENABLED=true
102
+ - N8N_RUNNERS_MODE=external
103
+ - N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
104
+ - N8N_RUNNERS_AUTH_TOKEN=test
105
+ command: worker
106
+ volumes:
107
+ - ${RUN_DIR}/n8n-worker2:/n8n
108
+ depends_on:
109
+ # We let the worker 1 start first so it can run the DB migrations
110
+ n8n_worker1:
111
+ condition: service_healthy
112
+ postgres:
113
+ condition: service_healthy
114
+ redis:
115
+ condition: service_healthy
116
+ healthcheck:
117
+ test: ['CMD-SHELL', 'wget --spider -q http://localhost:5678/healthz || exit 1']
118
+ interval: 5s
119
+ timeout: 5s
120
+ retries: 10
121
+
122
+ n8n_worker2_runners:
123
+ image: ghcr.io/n8n-io/runners:${N8N_VERSION:-latest}
124
+ environment:
125
+ - N8N_RUNNERS_TASK_BROKER_URI=http://n8n_worker2:5679
126
+ - N8N_RUNNERS_AUTH_TOKEN=test
127
+ - NO_COLOR=1
128
+ depends_on:
129
+ n8n_worker2:
130
+ condition: service_healthy
131
+
132
+ n8n_main2:
133
+ image: ghcr.io/n8n-io/n8n:${N8N_VERSION:-latest}
134
+ environment:
135
+ - N8N_DIAGNOSTICS_ENABLED=false
136
+ - N8N_USER_FOLDER=/n8n
137
+ - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
138
+ - N8N_LICENSE_CERT=${N8N_LICENSE_CERT}
139
+ - N8N_LICENSE_ACTIVATION_KEY=${N8N_LICENSE_ACTIVATION_KEY}
140
+ - N8N_LICENSE_TENANT_ID=${N8N_LICENSE_TENANT_ID}
141
+ # Scaling mode config
142
+ - N8N_PROXY_HOPS=1
143
+ - EXECUTIONS_MODE=queue
144
+ - QUEUE_BULL_REDIS_HOST=redis
145
+ - N8N_MULTI_MAIN_SETUP_ENABLED=true
146
+ # DB config
147
+ - DB_TYPE=postgresdb
148
+ - DB_POSTGRESDB_HOST=postgres
149
+ - DB_POSTGRESDB_PASSWORD=password
150
+ - N8N_METRICS=true
151
+ volumes:
152
+ - ${RUN_DIR}/n8n-main2:/n8n
153
+ depends_on:
154
+ n8n_worker1:
155
+ condition: service_healthy
156
+ n8n_worker2:
157
+ condition: service_healthy
158
+ postgres:
159
+ condition: service_healthy
160
+ redis:
161
+ condition: service_healthy
162
+ mockapi:
163
+ condition: service_started
164
+ healthcheck:
165
+ test: ['CMD-SHELL', 'wget --spider -q http://n8n_main2:5678/healthz || exit 1']
166
+ interval: 5s
167
+ timeout: 5s
168
+ retries: 10
169
+
170
+ n8n_main1:
171
+ image: ghcr.io/n8n-io/n8n:${N8N_VERSION:-latest}
172
+ environment:
173
+ - N8N_DIAGNOSTICS_ENABLED=false
174
+ - N8N_USER_FOLDER=/n8n
175
+ - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
176
+ - N8N_LICENSE_CERT=${N8N_LICENSE_CERT}
177
+ - N8N_LICENSE_ACTIVATION_KEY=${N8N_LICENSE_ACTIVATION_KEY}
178
+ - N8N_LICENSE_TENANT_ID=${N8N_LICENSE_TENANT_ID}
179
+ # Scaling mode config
180
+ - N8N_PROXY_HOPS=1
181
+ - EXECUTIONS_MODE=queue
182
+ - QUEUE_BULL_REDIS_HOST=redis
183
+ - N8N_MULTI_MAIN_SETUP_ENABLED=true
184
+ # DB config
185
+ - DB_TYPE=postgresdb
186
+ - DB_POSTGRESDB_HOST=postgres
187
+ - DB_POSTGRESDB_PASSWORD=password
188
+ - N8N_METRICS=true
189
+ volumes:
190
+ - ${RUN_DIR}/n8n-main1:/n8n
191
+ depends_on:
192
+ n8n_worker1:
193
+ condition: service_healthy
194
+ n8n_worker2:
195
+ condition: service_healthy
196
+ postgres:
197
+ condition: service_healthy
198
+ redis:
199
+ condition: service_healthy
200
+ mockapi:
201
+ condition: service_started
202
+ healthcheck:
203
+ test: ['CMD-SHELL', 'wget --spider -q http://n8n_main1:5678/healthz || exit 1']
204
+ interval: 5s
205
+ timeout: 5s
206
+ retries: 10
207
+
208
+ # Load balancer that acts as an entry point for n8n
209
+ n8n:
210
+ image: nginx:1.27.2
211
+ ports:
212
+ - '5678:80'
213
+ volumes:
214
+ - ./nginx.conf:/etc/nginx/nginx.conf
215
+ depends_on:
216
+ n8n_main1:
217
+ condition: service_healthy
218
+ n8n_main2:
219
+ condition: service_healthy
220
+
221
+ benchmark:
222
+ image: ghcr.io/n8n-io/n8n-benchmark:${N8N_BENCHMARK_VERSION:-latest}
223
+ depends_on:
224
+ - n8n
225
+ environment:
226
+ - N8N_BASE_URL=http://n8n:80
227
+ - K6_API_TOKEN=${K6_API_TOKEN}
228
+ - BENCHMARK_RESULT_WEBHOOK_URL=${BENCHMARK_RESULT_WEBHOOK_URL}
229
+ - BENCHMARK_RESULT_WEBHOOK_AUTH_HEADER=${BENCHMARK_RESULT_WEBHOOK_AUTH_HEADER}
230
+ - COLLECT_APP_METRICS=true
@@ -0,0 +1,24 @@
1
+ events {}
2
+
3
+ http {
4
+ client_max_body_size 50M;
5
+ access_log off;
6
+ error_log /dev/stderr warn;
7
+
8
+ upstream backend {
9
+ server n8n_main1:5678;
10
+ server n8n_main2:5678;
11
+ }
12
+
13
+ server {
14
+ listen 80;
15
+
16
+ location / {
17
+ proxy_pass http://backend;
18
+ proxy_set_header Host $host;
19
+ proxy_set_header X-Real-IP $remote_addr;
20
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
21
+ proxy_set_header X-Forwarded-Proto $scheme;
22
+ }
23
+ }
24
+ }
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env zx
2
+
3
+ import path from 'path';
4
+ import { fs } from 'zx';
5
+
6
+ /**
7
+ * Creates the needed directories so the permissions get set correctly.
8
+ */
9
+ export function setup({ runDir }) {
10
+ const neededDirs = ['n8n-worker1', 'n8n-worker2', 'n8n-main1', 'n8n-main2', 'postgres'];
11
+
12
+ for (const dir of neededDirs) {
13
+ fs.ensureDirSync(path.join(runDir, dir));
14
+ }
15
+ }
@@ -0,0 +1,174 @@
1
+ services:
2
+ mockapi:
3
+ image: wiremock/wiremock:3.9.1
4
+ ports:
5
+ - '8088:8080'
6
+ volumes:
7
+ - ${MOCK_API_DATA_PATH}/mappings:/home/wiremock/mappings
8
+
9
+ redis:
10
+ image: redis:6.2.14-alpine
11
+ ports:
12
+ - 6379:6379
13
+ healthcheck:
14
+ test: ['CMD', 'redis-cli', 'ping']
15
+ interval: 1s
16
+ timeout: 3s
17
+
18
+ postgres:
19
+ image: postgres:16.4
20
+ user: root:root
21
+ restart: always
22
+ environment:
23
+ - POSTGRES_DB=n8n
24
+ - POSTGRES_USER=postgres
25
+ - POSTGRES_PASSWORD=password
26
+ - PGDATA=/var/lib/postgresql/data/pgdata
27
+ volumes:
28
+ - ${RUN_DIR}/postgres:/var/lib/postgresql/data
29
+ healthcheck:
30
+ test: ['CMD-SHELL', 'pg_isready -U postgres']
31
+ interval: 5s
32
+ timeout: 5s
33
+ retries: 10
34
+
35
+ n8n_worker1:
36
+ image: ghcr.io/n8n-io/n8n:${N8N_VERSION:-latest}
37
+ user: root:root
38
+ environment:
39
+ - N8N_DIAGNOSTICS_ENABLED=false
40
+ - N8N_USER_FOLDER=/n8n/worker1
41
+ - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
42
+ # Queue mode config
43
+ - EXECUTIONS_MODE=queue
44
+ - QUEUE_BULL_REDIS_HOST=redis
45
+ - QUEUE_HEALTH_CHECK_ACTIVE=true
46
+ - N8N_CONCURRENCY_PRODUCTION_LIMIT=10
47
+ # DB config
48
+ - DB_TYPE=postgresdb
49
+ - DB_POSTGRESDB_HOST=postgres
50
+ - DB_POSTGRESDB_PASSWORD=password
51
+ # Task Runner config
52
+ - N8N_RUNNERS_ENABLED=true
53
+ - N8N_RUNNERS_MODE=external
54
+ - N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
55
+ - N8N_RUNNERS_AUTH_TOKEN=test
56
+ command: worker
57
+ volumes:
58
+ - ${RUN_DIR}/n8n-worker1:/n8n
59
+ depends_on:
60
+ postgres:
61
+ condition: service_healthy
62
+ redis:
63
+ condition: service_healthy
64
+ healthcheck:
65
+ test: ['CMD-SHELL', 'wget --spider -q http://n8n_worker1:5678/healthz || exit 1']
66
+ interval: 5s
67
+ timeout: 5s
68
+ retries: 10
69
+
70
+ n8n_worker1_runners:
71
+ image: ghcr.io/n8n-io/runners:${N8N_VERSION:-latest}
72
+ environment:
73
+ - N8N_RUNNERS_TASK_BROKER_URI=http://n8n_worker1:5679
74
+ - N8N_RUNNERS_AUTH_TOKEN=test
75
+ - NO_COLOR=1
76
+ depends_on:
77
+ n8n_worker1:
78
+ condition: service_healthy
79
+
80
+ n8n_worker2:
81
+ image: ghcr.io/n8n-io/n8n:${N8N_VERSION:-latest}
82
+ user: root:root
83
+ environment:
84
+ - N8N_DIAGNOSTICS_ENABLED=false
85
+ - N8N_USER_FOLDER=/n8n/worker2
86
+ - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
87
+ # Queue mode config
88
+ - EXECUTIONS_MODE=queue
89
+ - QUEUE_BULL_REDIS_HOST=redis
90
+ - QUEUE_HEALTH_CHECK_ACTIVE=true
91
+ - N8N_CONCURRENCY_PRODUCTION_LIMIT=10
92
+ # DB config
93
+ - DB_TYPE=postgresdb
94
+ - DB_POSTGRESDB_HOST=postgres
95
+ - DB_POSTGRESDB_PASSWORD=password
96
+ # Task Runner config
97
+ - N8N_RUNNERS_ENABLED=true
98
+ - N8N_RUNNERS_MODE=external
99
+ - N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
100
+ - N8N_RUNNERS_AUTH_TOKEN=test
101
+ command: worker
102
+ volumes:
103
+ - ${RUN_DIR}/n8n-worker2:/n8n
104
+ depends_on:
105
+ # We let the worker 1 start first so it can run the DB migrations
106
+ n8n_worker1:
107
+ condition: service_healthy
108
+ postgres:
109
+ condition: service_healthy
110
+ redis:
111
+ condition: service_healthy
112
+ healthcheck:
113
+ test: ['CMD-SHELL', 'wget --spider -q http://n8n_worker2:5678/healthz || exit 1']
114
+ interval: 5s
115
+ timeout: 5s
116
+ retries: 10
117
+
118
+ n8n_worker2_runners:
119
+ image: ghcr.io/n8n-io/runners:${N8N_VERSION:-latest}
120
+ environment:
121
+ - N8N_RUNNERS_TASK_BROKER_URI=http://n8n_worker2:5679
122
+ - N8N_RUNNERS_AUTH_TOKEN=test
123
+ - NO_COLOR=1
124
+ depends_on:
125
+ n8n_worker2:
126
+ condition: service_healthy
127
+
128
+ n8n:
129
+ image: ghcr.io/n8n-io/n8n:${N8N_VERSION:-latest}
130
+ user: root:root
131
+ environment:
132
+ - N8N_DIAGNOSTICS_ENABLED=false
133
+ - N8N_USER_FOLDER=/n8n/main
134
+ - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
135
+ # Queue mode config
136
+ - EXECUTIONS_MODE=queue
137
+ - QUEUE_BULL_REDIS_HOST=redis
138
+ # DB config
139
+ - DB_TYPE=postgresdb
140
+ - DB_POSTGRESDB_HOST=postgres
141
+ - DB_POSTGRESDB_PASSWORD=password
142
+ - N8N_METRICS=true
143
+ ports:
144
+ - 5678:5678
145
+ volumes:
146
+ - ${RUN_DIR}/n8n-main:/n8n
147
+ depends_on:
148
+ n8n_worker1:
149
+ condition: service_healthy
150
+ n8n_worker2:
151
+ condition: service_healthy
152
+ postgres:
153
+ condition: service_healthy
154
+ redis:
155
+ condition: service_healthy
156
+ mockapi:
157
+ condition: service_started
158
+ healthcheck:
159
+ test: ['CMD-SHELL', 'wget --spider -q http://n8n:5678/healthz || exit 1']
160
+ interval: 5s
161
+ timeout: 5s
162
+ retries: 10
163
+
164
+ benchmark:
165
+ image: ghcr.io/n8n-io/n8n-benchmark:${N8N_BENCHMARK_VERSION:-latest}
166
+ depends_on:
167
+ n8n:
168
+ condition: service_healthy
169
+ environment:
170
+ - N8N_BASE_URL=http://n8n:5678
171
+ - K6_API_TOKEN=${K6_API_TOKEN}
172
+ - BENCHMARK_RESULT_WEBHOOK_URL=${BENCHMARK_RESULT_WEBHOOK_URL}
173
+ - BENCHMARK_RESULT_WEBHOOK_AUTH_HEADER=${BENCHMARK_RESULT_WEBHOOK_AUTH_HEADER}
174
+ - COLLECT_APP_METRICS=true
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env zx
2
+
3
+ import path from 'path';
4
+ import { fs } from 'zx';
5
+
6
+ /**
7
+ * Creates the needed directories so the permissions get set correctly.
8
+ */
9
+ export function setup({ runDir }) {
10
+ const neededDirs = ['n8n-worker1', 'n8n-worker2', 'n8n-main', 'postgres'];
11
+
12
+ for (const dir of neededDirs) {
13
+ fs.ensureDirSync(path.join(runDir, dir));
14
+ }
15
+ }
@@ -0,0 +1,55 @@
1
+ services:
2
+ mockapi:
3
+ image: wiremock/wiremock:3.9.1
4
+ ports:
5
+ - '8088:8080'
6
+ volumes:
7
+ - ${MOCK_API_DATA_PATH}/mappings:/home/wiremock/mappings
8
+
9
+ n8n:
10
+ image: ghcr.io/n8n-io/n8n:${N8N_VERSION:-latest}
11
+ user: root:root
12
+ environment:
13
+ - N8N_DIAGNOSTICS_ENABLED=false
14
+ - N8N_USER_FOLDER=/n8n
15
+ - DB_SQLITE_POOL_SIZE=3
16
+ - DB_SQLITE_ENABLE_WAL=true
17
+ # Task Runner config
18
+ - N8N_RUNNERS_ENABLED=true
19
+ - N8N_RUNNERS_MODE=external
20
+ - N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0
21
+ - N8N_RUNNERS_AUTH_TOKEN=test
22
+ - N8N_METRICS=true
23
+ ports:
24
+ - 5678:5678
25
+ volumes:
26
+ - ${RUN_DIR}:/n8n
27
+ healthcheck:
28
+ test: ['CMD-SHELL', 'wget --spider -q http://n8n:5678/healthz || exit 1']
29
+ interval: 5s
30
+ timeout: 5s
31
+ retries: 10
32
+ depends_on:
33
+ mockapi:
34
+ condition: service_started
35
+
36
+ runners:
37
+ image: ghcr.io/n8n-io/runners:${N8N_VERSION:-latest}
38
+ environment:
39
+ - N8N_RUNNERS_TASK_BROKER_URI=http://n8n:5679
40
+ - N8N_RUNNERS_AUTH_TOKEN=test
41
+ - NO_COLOR=1
42
+ depends_on:
43
+ n8n:
44
+ condition: service_healthy
45
+
46
+ benchmark:
47
+ image: ghcr.io/n8n-io/n8n-benchmark:${N8N_BENCHMARK_VERSION:-latest}
48
+ depends_on:
49
+ n8n:
50
+ condition: service_healthy
51
+ environment:
52
+ - N8N_BASE_URL=http://n8n:5678
53
+ - K6_API_TOKEN=${K6_API_TOKEN}
54
+ - BENCHMARK_RESULT_WEBHOOK_URL=${BENCHMARK_RESULT_WEBHOOK_URL}
55
+ - BENCHMARK_RESULT_WEBHOOK_AUTH_HEADER=${BENCHMARK_RESULT_WEBHOOK_AUTH_HEADER}
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env zx
2
+
3
+ import path from 'path';
4
+ import { fs } from 'zx';
5
+
6
+ /**
7
+ * Creates the needed directories so the permissions get set correctly.
8
+ */
9
+ export function setup({ runDir }) {
10
+ const neededDirs = ['n8n'];
11
+
12
+ for (const dir of neededDirs) {
13
+ fs.ensureDirSync(path.join(runDir, dir));
14
+ }
15
+ }
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env zx
2
+ /**
3
+ * Provisions the cloud benchmark environment
4
+ *
5
+ * NOTE: Must be run in the root of the package.
6
+ */
7
+ // @ts-check
8
+ import { which, minimist } from 'zx';
9
+ import { TerraformClient } from './clients/terraform-client.mjs';
10
+
11
+ const args = minimist(process.argv.slice(3), {
12
+ boolean: ['debug'],
13
+ });
14
+
15
+ const isVerbose = !!args.debug;
16
+
17
+ export async function provision() {
18
+ await ensureDependencies();
19
+
20
+ const terraformClient = new TerraformClient({
21
+ isVerbose,
22
+ });
23
+
24
+ await terraformClient.provisionEnvironment();
25
+ }
26
+
27
+ async function ensureDependencies() {
28
+ await which('terraform');
29
+ }
30
+
31
+ provision().catch((error) => {
32
+ console.error('An error occurred while provisioning cloud env:');
33
+ console.error(error);
34
+
35
+ process.exit(1);
36
+ });