<figure class="wp-block-image aligncenter"><img src="https://flowgenius.in/wp-content/uploads/2026/01/cpu-profiling.png" alt="Step by Step Guide to solve cpu profiling" /><figcaption style="text-align: center;">Step by Step Guide to solve cpu profiling</p>
<hr />
</figcaption></figure>
<p style="margin-bottom: 2em; line-height: 1.9;"><strong>Who this is for: </strong>Developers and DevOps engineers who maintain n8n instances and need to diagnose CPU‑bound performance problems in production or staging environments. <strong>We cover this in detail in the </strong><a href="https://flowgenius.in/n8n-performance-and-scaling-guide/">n8n Performance & Scaling Guide.</a></p>
<hr />
<h2></h2>
<h2 style="margin-bottom: 45px; line-height: 1.3;">Quick Diagnosis</h2>
<p style="margin-bottom: 2em; line-height: 1.9;"><strong>Problem:</strong> An n8n instance feels sluggish and you suspect specific nodes or workflows are hogging CPU.</p>
<p style="margin-bottom: 2em; line-height: 1.9;"><strong>One‑line fix:</strong> Run a Node.js profiler (e.g., <code>clinic flame</code>, <code>0x</code>, or V8’s built‑in <code>--prof</code>) against the n8n process, generate a flame‑graph, and zero in on the hot functions.</p>
<p style="margin-bottom: 2em; line-height: 1.9;"><strong>Featured‑snippet steps</strong></p>
<ol style="margin-bottom: 1.7em; line-height: 1.9;">
<li>Stop the running n8n service.</li>
<li>Start n8n with a profiling flag.</li>
<li>Trigger the slow workflow (or run a load test).</li>
<li>Stop n8n and generate a flame‑graph.</li>
<li>Open the SVG/HTML graph, locate the longest stack traces, and optimise the offending node or custom code.</li>
</ol>
<div style="margin: 55px 0;">
<hr />
</div>
<h2 style="margin-bottom: 45px; line-height: 1.3;">1. Prerequisites</h2>
<p>If you encounter any <a href="/docker-performance-tuning">docker performance tuning </a>resolve them before continuing with the setup.</p>
<table style="border-collapse: collapse; width: 100%; margin-bottom: 2em;">
<thead>
<tr>
<th style="border: 1px solid #e0e0e0; padding: 13px;">Requirement</th>
<th style="border: 1px solid #e0e0e0; padding: 13px;">Why it matters</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;"><strong>n8n ≥ 0.230</strong></td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Profiling hooks are stable from this release onward</td>
</tr>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;"><strong>Node.js ≥ 18</strong></td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Modern V8 provides richer <code>--prof</code> output</td>
</tr>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;"><strong>Profiling tool</strong> (choose one)</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Generates flame‑graphs or CPU‑time breakdowns</td>
</tr>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;"><strong>Host access</strong> (SSH / terminal)</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Needed to start n8n with custom flags</td>
</tr>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;"><strong>Docker host (optional)</strong></td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Required if n8n runs inside a container</td>
</tr>
</tbody>
</table>
<blockquote style="margin-bottom: 2em; line-height: 1.9;"><p><strong>EEFA note:</strong> Never expose <code>--inspect</code> to the public internet. Bind the inspector to <code>127.0.0.1</code> or tunnel through a VPN.</p></blockquote>
<div style="margin: 55px 0;">
<hr />
</div>
<h2 style="margin-bottom: 45px; line-height: 1.3;">2. Starting n8n with a Profiler</h2>
<h3 style="margin-bottom: 45px; line-height: 1.3;">2.1 Bare‑metal (direct Node execution)</h3>
<p style="margin-bottom: 2em; line-height: 1.9;">Stop any existing service and launch n8n with V8’s CPU profiler.</p>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto; margin-bottom: 2em;">pm2 stop n8n # or: systemctl stop n8n
node --prof \
--max-old-space-size=4096 \
./node_modules/.bin/n8n &
</pre>
<p style="margin-bottom: 2em; line-height: 1.9;">The <code>--prof</code> flag creates <code>isolate-*.log</code> files in the current directory. The memory flag prevents OOM crashes during long runs.</p>
<h3 style="margin-bottom: 45px; line-height: 1.3;">2.2 Using <strong>clinic flame</strong> (recommended for visual output)</h3>
<p style="margin-bottom: 2em; line-height: 1.9;">Clinic handles process spawning, data collection, and graph generation automatically.</p>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto; margin-bottom: 2em;">npm i -g clinic
clinic flame -- node ./node_modules/.bin/n8n
</pre>
<p style="margin-bottom: 2em; line-height: 1.9;">Press <code>Ctrl+C</code> when the workload is done; <code>flamegraph.html</code> appears in the cwd.</p>
<h3 style="margin-bottom: 45px; line-height: 1.3;">2.3 Profiling a Docker‑based n8n</h3>
<ol style="margin-bottom: 1.7em; line-height: 1.9;">
<li><strong>Enter the container with privileged rights</strong> (required for V8 profiling).</li>
</ol>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto; margin-bottom: 2em;">docker ps | grep n8n # get the container ID
docker exec -it --privileged <container-id> sh
</pre>
<ol style="margin-bottom: 1.7em; line-height: 1.9;" start="2">
<li><strong>Install the profiler inside the container</strong> and run it.</li>
</ol>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto; margin-bottom: 2em;">npm i -g clinic
clinic flame -- node /usr/local/bin/n8n
</pre>
<blockquote style="margin-bottom: 2em; line-height: 1.9;"><p><strong>EEFA warning:</strong> <code>--privileged</code> grants full host kernel access. Use only on isolated staging containers. If you encounter any <a href="/resource-limiting-with-cgroups">resource limiting with cgroups </a>resolve them before continuing with the setup.</p></blockquote>
<div style="margin: 55px 0;">
<hr />
</div>
<h2 style="margin-bottom: 45px; line-height: 1.3;">3. Capturing a Representative Workload</h2>
<table style="border-collapse: collapse; width: 100%; margin-bottom: 2em;">
<thead>
<tr>
<th style="border: 1px solid #e0e0e0; padding: 13px;">Approach</th>
<th style="border: 1px solid #e0e0e0; padding: 13px;">When to use</th>
<th style="border: 1px solid #e0e0e0; padding: 13px;">How to trigger</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Manual execution</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Quick sanity check, low traffic</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Click <strong>Execute Workflow</strong> in the UI</td>
</tr>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Automated load test</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">High‑traffic scenarios</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;"><code>k6 run -d 30s -u 50 script.js</code> (target the <code>/webhook</code> endpoint)</td>
</tr>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Scheduled cron job</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Periodic background jobs</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Let the native n8n cron trigger run naturally</td>
</tr>
</tbody>
</table>
<p style="margin-bottom: 2em; line-height: 1.9;"><em>Tip:</em> Keep profiling sessions <strong>≤ 60 seconds</strong>. Longer runs produce massive <code>isolate</code> files and may skew results due to JIT warm‑up.</p>
<div style="margin: 55px 0;">
<hr />
</div>
<h2 style="margin-bottom: 45px; line-height: 1.3;">4. Converting Logs to Flame‑Graphs</h2>
<h3 style="margin-bottom: 45px; line-height: 1.3;">4.1 V8’s <code>--prof-process</code> pipeline</h3>
<ol style="margin-bottom: 1.7em; line-height: 1.9;">
<li><strong>Find the latest isolate file.</strong></li>
</ol>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto; margin-bottom: 2em;">ls -1t isolate-*.log | head -n1
</pre>
<ol style="margin-bottom: 1.7em; line-height: 1.9;" start="2">
<li><strong>Convert to a readable text report.</strong></li>
</ol>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto; margin-bottom: 2em;">node --prof-process isolate-00000-v8.log > processed.txt
</pre>
<ol style="margin-bottom: 1.7em; line-height: 1.9;" start="3">
<li><strong>Render an SVG flame‑graph</strong> (requires <code>gprof2dot</code> and Graphviz).</li>
</ol>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto; margin-bottom: 2em;">cat processed.txt | gprof2dot -s | dot -Tsvg -o cpu.svg
</pre>
<p style="margin-bottom: 2em; line-height: 1.9;">Open <code>cpu.svg</code> in a browser; the widest bars indicate the highest CPU consumption.</p>
<h3 style="margin-bottom: 45px; line-height: 1.3;">4.2 Clinic flame (auto‑generated)</h3>
<p style="margin-bottom: 2em; line-height: 1.9;">Run the same command from §2.2; after workload completion, <code>flamegraph.html</code> is ready—no extra steps needed.</p>
<table style="border-collapse: collapse; width: 100%; margin-bottom: 2em;">
<thead>
<tr>
<th style="border: 1px solid #e0e0e0; padding: 13px;">Tool</th>
<th style="border: 1px solid #e0e0e0; padding: 13px;">Output</th>
<th style="border: 1px solid #e0e0e0; padding: 13px;">Best for</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;">–prof-process + gprof2dot</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">SVG flame‑graph</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Full control, custom post‑processing</td>
</tr>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;"><strong>clinic flame</strong></td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Interactive HTML</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Fast turnaround, beginner‑friendly</td>
</tr>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;">0x</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Chrome‑compatible flame‑graph</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">When you prefer Chrome DevTools UI</td>
</tr>
</tbody>
</table>
<div style="margin: 55px 0;">
<hr />
</div>
<h2 style="margin-bottom: 45px; line-height: 1.3;">5. Interpreting the Flame‑Graph</h2>
<ol style="margin-bottom: 1.7em; line-height: 1.9;">
<li><strong>Find the longest horizontal bar</strong> – this is the hottest stack trace.</li>
<li><strong>Read bottom‑to‑top</strong> – the bottom function is where execution started (often <code>runWorkflow</code>).</li>
<li><strong>Spot custom code</strong> – look for paths like <code>functions/</code> or your own npm packages.</li>
<li><strong>Identify built‑in nodes</strong> – names such as <code>ExecuteCommand</code>, <code>HttpRequest</code>, or <code>Code</code> appear as <code>nodeExecute</code> wrappers.</li>
<li>If you encounter any <a href="/custom-node-performance">custom node performance </a>resolve them before continuing with the setup.</li>
</ol>
<p style="margin-bottom: 2em; line-height: 1.9;"><strong>Example textual snippet</strong></p>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto; margin-bottom: 2em;">runWorkflow → executeNode → executeCodeNode → eval (my-custom-function.js:23)
</pre>
<p style="margin-bottom: 2em; line-height: 1.9;">Action: The <code>eval</code> call at line 23 in <code>my‑custom‑function.js</code> is the hotspot. Refactor the loop, cache results, or move the logic to an external micro‑service.</p>
<div style="margin: 55px 0;">
<hr />
</div>
<h2 style="margin-bottom: 45px; line-height: 1.3;">6. Optimising Identified Hot Nodes</h2>
<table style="border-collapse: collapse; width: 100%; margin-bottom: 2em;">
<thead>
<tr>
<th style="border: 1px solid #e0e0e0; padding: 13px;">Issue</th>
<th style="border: 1px solid #e0e0e0; padding: 13px;">Typical cause</th>
<th style="border: 1px solid #e0e0e0; padding: 13px;">Quick fix</th>
<th style="border: 1px solid #e0e0e0; padding: 13px;">Production‑grade fix</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;">CPU‑bound JS loop</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;"><code>for</code> over 10⁶ items</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Switch to <code>Array.reduce</code> with early exit</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Stream data via a <strong>Node.js Transform</strong> or offload to a worker thread (<code>worker_threads</code>)</td>
</tr>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Repeated external API calls</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;"><code>HttpRequest</code> inside a loop</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Batch with <code>Promise.allSettled</code></td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Add a <strong>caching layer</strong> (Redis) and respect rate limits</td>
</tr>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Heavy file parsing</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;"><code>ReadBinaryFile</code> + <code>ParseCSV</code></td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Limit rows via <code>skipRows</code></td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Pre‑process files with an ETL service (e.g., AWS Lambda)</td>
</tr>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Sync I/O in custom code</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;"><code>fs.readFileSync</code> inside a loop</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Use async <code>fs.promises.readFile</code></td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Switch to streams (<code>fs.createReadStream</code>) to avoid blocking the event loop</td>
</tr>
</tbody>
</table>
<blockquote style="margin-bottom: 2em; line-height: 1.9;"><p><strong>EEFA tip:</strong> Re‑run the profiler after each change. Hotspots shift; iterative profiling prevents regression.</p></blockquote>
<div style="margin: 55px 0;">
<hr />
</div>
<h2 style="margin-bottom: 45px; line-height: 1.3;">7. Common Profiling Pitfalls</h2>
<table style="border-collapse: collapse; width: 100%; margin-bottom: 2em;">
<thead>
<tr>
<th style="border: 1px solid #e0e0e0; padding: 13px;">Symptom</th>
<th style="border: 1px solid #e0e0e0; padding: 13px;">Root cause</th>
<th style="border: 1px solid #e0e0e0; padding: 13px;">Fix</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;">No <code>isolate-*.log</code> generated</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Used <code>--inspect</code> instead of <code>--prof</code></td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Launch with <code>node --prof …</code></td>
</tr>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Flame‑graph shows only V8 internals</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Workload too short; JIT never warmed up</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Run the workload for <strong>≥ 30 s</strong> or increase iterations</td>
</tr>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Huge <code>isolate</code> files (> 500 MB)</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Profiling over an extended period or high concurrency</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Limit concurrency, profile a single workflow only</td>
</tr>
<tr>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Profiler crashes in Docker</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;">Missing <code>perf</code> binary (required by <code>clinic</code>)</td>
<td style="border: 1px solid #e0e0e0; padding: 13px;"><code>apt-get update && apt-get install -y linux-tools-common linux-tools-generic</code> **or** use <code>clinic</code> with <code>--collect-only</code></td>
</tr>
</tbody>
</table>
<div style="margin: 55px 0;">
<hr />
</div>
<h2 style="margin-bottom: 45px; line-height: 1.3;">8. Automating CPU Profiling in CI/CD</h2>
<h3 style="margin-bottom: 45px; line-height: 1.3;">8.1 Workflow definition (GitHub Actions)</h3>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto; margin-bottom: 2em;">name: CPU profiling (staging)
on:
workflow_dispatch:
inputs:
workflowId:
description: "n8n workflow ID to profile"
required: true
</pre>
<h3 style="margin-bottom: 45px; line-height: 1.3;">8.2 Job steps – install and start profiling</h3>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto; margin-bottom: 2em;">jobs:
profile:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install n8n & clinic
run: |
npm ci
npm i -g clinic
</pre>
<h3 style="margin-bottom: 45px; line-height: 1.3;">8.3 Run n8n with profiling, trigger the workflow, then stop</h3>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto; margin-bottom: 2em;"> - name: Start n8n with profiling
run: |
clinic flame -- node ./node_modules/.bin/n8n &
N8N_PID=$!
sleep 5 # give n8n time to start
curl -X POST "https://staging.example.com/webhook/${{ github.event.inputs.workflowId }}"
kill $N8N_PID
</pre>
<h3 style="margin-bottom: 45px; line-height: 1.3;">8.4 Upload the resulting flame‑graph as an artifact</h3>
<pre style="background: #fafafa; padding: 20px; border: 1px solid #e0e0e0; overflow: auto; margin-bottom: 2em;"> - name: Upload flamegraph
uses: actions/upload-artifact@v3
with:
name: flamegraph
path: flamegraph.html
</pre>
<p style="margin-bottom: 2em; line-height: 1.9;">Result: Each manual dispatch creates a fresh flame‑graph stored as a CI artifact, enabling continuous performance regression detection.</p>
<div style="margin: 55px 0;">
<hr />
</div>
<h3 style="margin-bottom: 45px; line-height: 1.3;">Conclusion</h3>
<p style="margin-bottom: 2em; line-height: 1.9;">CPU profiling in n8n follows a repeatable loop:</p>
<ol style="margin-bottom: 1.7em; line-height: 1.9;">
<li><strong>Start</strong> the process with a profiler (<code>--prof</code> or <code>clinic flame</code>).</li>
<li><strong>Exercise</strong> the suspect workflow under realistic load.</li>
<li><strong>Generate</strong> a flame‑graph and locate the widest stack trace.</li>
<li><strong>Optimise</strong> the offending node or custom code (loop refactor, batching, caching, async I/O, or worker off‑loading).</li>
<li><strong>Re‑profile</strong> to confirm the improvement.</li>
</ol>
<p style="margin-bottom: 2em; line-height: 1.9;">By integrating profiling into CI/CD, you catch regressions early and keep your n8n automations performant in production.</p>
Step by Step Guide to solve cpu profiling
Who this is for: Developers and DevOps engineers who maintain n8n instances and need to diagnose CPU‑bound performance problems in production or staging environments. We cover this in detail in the n8n Performance & Scaling Guide.
Quick Diagnosis
Problem: An n8n instance feels sluggish and you suspect specific nodes or workflows are hogging CPU.
One‑line fix: Run a Node.js profiler (e.g., clinic flame, 0x, or V8’s built‑in --prof) against the n8n process, generate a flame‑graph, and zero in on the hot functions.
Featured‑snippet steps
Stop the running n8n service.
Start n8n with a profiling flag.
Trigger the slow workflow (or run a load test).
Stop n8n and generate a flame‑graph.
Open the SVG/HTML graph, locate the longest stack traces, and optimise the offending node or custom code.
The --prof flag creates isolate-*.log files in the current directory. The memory flag prevents OOM crashes during long runs.
2.2 Using clinic flame (recommended for visual output)
Clinic handles process spawning, data collection, and graph generation automatically.
npm i -g clinic
clinic flame -- node ./node_modules/.bin/n8n
Press Ctrl+C when the workload is done; flamegraph.html appears in the cwd.
2.3 Profiling a Docker‑based n8n
Enter the container with privileged rights (required for V8 profiling).
docker ps | grep n8n # get the container ID
docker exec -it --privileged <container-id> sh
Install the profiler inside the container and run it.
npm i -g clinic
clinic flame -- node /usr/local/bin/n8n
EEFA warning:--privileged grants full host kernel access. Use only on isolated staging containers. If you encounter any resource limiting with cgroups resolve them before continuing with the setup.
3. Capturing a Representative Workload
Approach
When to use
How to trigger
Manual execution
Quick sanity check, low traffic
Click Execute Workflow in the UI
Automated load test
High‑traffic scenarios
k6 run -d 30s -u 50 script.js (target the /webhook endpoint)
Scheduled cron job
Periodic background jobs
Let the native n8n cron trigger run naturally
Tip: Keep profiling sessions ≤ 60 seconds. Longer runs produce massive isolate files and may skew results due to JIT warm‑up.
Action: The eval call at line 23 in my‑custom‑function.js is the hotspot. Refactor the loop, cache results, or move the logic to an external micro‑service.
6. Optimising Identified Hot Nodes
Issue
Typical cause
Quick fix
Production‑grade fix
CPU‑bound JS loop
for over 10⁶ items
Switch to Array.reduce with early exit
Stream data via a Node.js Transform or offload to a worker thread (worker_threads)
Repeated external API calls
HttpRequest inside a loop
Batch with Promise.allSettled
Add a caching layer (Redis) and respect rate limits
Heavy file parsing
ReadBinaryFile + ParseCSV
Limit rows via skipRows
Pre‑process files with an ETL service (e.g., AWS Lambda)
Sync I/O in custom code
fs.readFileSync inside a loop
Use async fs.promises.readFile
Switch to streams (fs.createReadStream) to avoid blocking the event loop
EEFA tip: Re‑run the profiler after each change. Hotspots shift; iterative profiling prevents regression.
7. Common Profiling Pitfalls
Symptom
Root cause
Fix
No isolate-*.log generated
Used --inspect instead of --prof
Launch with node --prof …
Flame‑graph shows only V8 internals
Workload too short; JIT never warmed up
Run the workload for ≥ 30 s or increase iterations
Huge isolate files (> 500 MB)
Profiling over an extended period or high concurrency
Limit concurrency, profile a single workflow only
Profiler crashes in Docker
Missing perf binary (required by clinic)
apt-get update && apt-get install -y linux-tools-common linux-tools-generic **or** use clinic with --collect-only
8. Automating CPU Profiling in CI/CD
8.1 Workflow definition (GitHub Actions)
name: CPU profiling (staging)
on:
workflow_dispatch:
inputs:
workflowId:
description: "n8n workflow ID to profile"
required: true