# Performance Profiling for Node.js, Python, and Go Applications: A Complete Guide

> Master performance profiling for Node.js, Python, and Go. This guide reveals how to find CPU, memory, and I/O bottlenecks with zero-instrumentation tools, keeping production code safe.

- Repository: [Alireza Rezvani/claude-skills](https://github.com/alirezarezvani/claude-skills)
- Tags: how-to-guide
- Published: 2026-03-09

---

**The Performance Profiler skill provides a systematic, language-agnostic workflow to identify CPU, memory, and I/O bottlenecks using zero-instrumentation tools like `clinic`, `py-spy`, and `go tool pprof`, ensuring production code remains untouched during analysis.**

This guide explores the Performance Profiler skill from the `alirezarezvani/claude-skills` repository, which standardizes performance optimization across backend stacks. It implements a rigorous *measure → profile → optimize → re-measure* cycle documented in [`docs/skills/engineering/performance-profiler.md`](https://github.com/alirezarezvani/claude-skills/blob/main/docs/skills/engineering/performance-profiler.md) to deliver consistent, data-driven improvements for Node.js, Python, and Go services.

## The Performance Profiler Architecture

The skill enforces a five-phase workflow that prevents false positives and builds a documented performance budget for CI pipelines.

### The Five-Phase Workflow

1. **Baseline Measurement** – Capture latency, error-rate, RPS, and memory usage using `curl` loops or k6 scripts before any code change.
2. **Profiling Phase** – Execute external profiling tools that attach to running processes without instrumentation.
3. **Analysis** – Render flamegraphs in Chrome DevTools or `speedscope.app` and inspect heap snapshots to locate hot paths, GC pressure, or memory leaks.
4. **Optimization** – Apply targeted fixes such as index creation, query batching, or dynamic imports.
5. **Re-measurement** – Run the identical load-test suite and compare metrics side-by-side using the built-in Markdown template.

The architecture emphasizes **single-change isolation**: modify one component at a time, re-run the profiler, and record delta values. This methodology ensures that every optimization is validated against a concrete baseline.

## Node.js Performance Profiling

Node.js profiling leverages the Clinic.js suite and custom scripts to analyze CPU usage and heap allocation without modifying application logic.

### CPU Analysis with `clinic flame`

The `clinic` tool generates flamegraphs that visualize V8 CPU consumption. Execute the following commands from [`docs/skills/engineering/performance-profiler.md`](https://github.com/alirezarezvani/claude-skills/blob/main/docs/skills/engineering/performance-profiler.md):

```bash

# Install once globally

npm install -g clinic

# Run a flamegraph while the server handles load

clinic flame -- node dist/server.js &
autocannon -c 50 -d 30 http://localhost:3000/api/tasks

```

The output produces [`clinic-flamegraph.html`](https://github.com/alirezarezvani/claude-skills/blob/main/clinic-flamegraph.html), revealing which functions dominate execution time. For event-loop diagnostics, combine this with `blocked-at` to log stalls.

### Memory Leak Detection

Use `clinic heapprofiler` for heap snapshots and the repository's `scripts/memory-profile.mjs` for automated regression testing. The script measures RSS and heap usage before and after forced garbage collection:

```javascript
// scripts/memory-profile.mjs
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
import fs from 'fs';

function formatBytes(b) { return (b/1024/1024).toFixed(2)+' MB'; }
function measure(label) {
  const m = process.memoryUsage();
  console.log(`\n[${label}] RSS:${formatBytes(m.rss)} HeapUsed:${formatBytes(m.heapUsed)}`);
  return m;
}
const base = measure('Baseline');
// ... run workload ...
global.gc?.(); // start node with --expose-gc
measure('After GC');

```

Execute with `node --experimental-vm-modules --expose-gc scripts/memory-profile.mjs`. A heap growth exceeding 10% after GC indicates a potential leak.

## Python Performance Profiling

Python profiling in this skill relies on external sampling and deterministic analysis tools that require no code rewrites.

### Live CPU Sampling with `py-spy`

`py-spy` attaches to a running process (e.g., FastAPI/Uvicorn) to generate flamegraphs without restarting the interpreter:

```bash
pip install py-spy

# Attach to a live process (PID 1234)

py-spy record -o flamegraph.svg --pid 1234 --duration 30

```

Open `flamegraph.svg` in a browser to identify which functions dominate CPU time. This approach is ideal for production environments where stopping the service is unacceptable.

### Deterministic and Memory Profiling

For detailed function-level timing, use `cProfile`. For line-by-line memory usage analysis, implement `memory_profiler` as referenced in [`docs/skills/engineering/performance-profiler.md`](https://github.com/alirezarezvani/claude-skills/blob/main/docs/skills/engineering/performance-profiler.md). These tools complement `py-spy` by providing deterministic data for local development and granular memory allocation tracking.

## Go Performance Profiling

Go’s profiling capabilities are built into the standard library, requiring only minimal import changes to expose HTTP endpoints.

### Built-in pprof Endpoints

Import `net/http/pprof` in your [`main.go`](https://github.com/alirezarezvani/claude-skills/blob/main/main.go) to automatically register debug handlers:

```go
package main

import (
    _ "net/http/pprof"
    "log"
    "net/http"
)

func main() {
    go func() {
        log.Println(http.ListenAndServe(":6060", nil))
    }()
    // ... rest of application ...
}

```

### Capturing and Visualizing Profiles

Fetch and visualize profiles using `go tool pprof`:

```bash

# Capture a 30-second CPU profile and open web UI

go tool pprof -http=:8080 http://localhost:6060/debug/pprof/profile?seconds=30

```

The web interface displays flamegraphs and call graphs for hot Goroutines. Heap profiles are available at `/debug/pprof/heap` using the same tool.

## Database Query Optimization

The skill integrates SQL analysis across all three languages. Use `EXPLAIN (ANALYZE, BUFFERS)` to pinpoint slow queries and detect N+1 patterns. For ORM-based applications (Django, Drizzle), enable query logging to identify redundant database round-trips before they reach production.

## Load Testing with k6

Load testing validates profiling results under realistic traffic. The repository includes [`tests/load/api-load-test.js`](https://github.com/alirezarezvani/claude-skills/blob/main/tests/load/api-load-test.js), a k6 scenario compatible with Node.js, Python, and Go backends:

```javascript
// tests/load/api-load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Rate, Trend } from 'k6/metrics';

export const options = {
  stages: [
    { duration: '30s', target: 10 },
    { duration: '1m',  target: 50 },
    { duration: '2m',  target: 50 },
    { duration: '30s', target: 100 },
    { duration: '1m',  target: 50 },
    { duration: '30s', target: 0 },
  ],
  thresholds: {
    http_req_duration: ['p(95)<500', 'p(99)<1000'],
    errors: ['rate<0.01'],
  },
};

const errorRate = new Rate('errors');

export default function () {
  const res = http.get(`${__ENV.BASE_URL}/api/tasks`);
  check(res, { 'status 200': (r) => r.status === 200 }) || errorRate.add(1);
  sleep(0.5);
}

```

Run the test with:

```bash
k6 run tests/load/api-load-test.js --env BASE_URL=http://localhost:3000

```

This script records latency percentiles (p95, p99), error rates, and custom trends, providing the metrics needed for the before/after comparison phase.

## Before/After Measurement and Reporting

The skill provides Markdown templates to document performance deltas. After optimization, teams re-run the identical k6 suite and populate the template with new metrics, creating an audit trail for CI/CD performance budgets. This reporting step is defined in [`engineering/performance-profiler/SKILL.md`](https://github.com/alirezarezvani/claude-skills/blob/main/engineering/performance-profiler/SKILL.md) and referenced throughout the documentation.

## Summary

- The Performance Profiler skill implements a *measure → profile → optimize → re-measure* cycle that prevents regressions through single-change isolation.
- **Node.js** applications use `clinic flame` and `clinic heapprofiler` for CPU and heap analysis, supplemented by `scripts/memory-profile.mjs` for leak detection.
- **Python** services leverage `py-spy` for live sampling and `memory_profiler` for line-by-line allocation tracking without code modification.
- **Go** programs utilize the built-in `net/http/pprof` package and `go tool pprof` for comprehensive CPU and heap visualization.
- All languages share **k6** load-testing scenarios from [`tests/load/api-load-test.js`](https://github.com/alirezarezvani/claude-skills/blob/main/tests/load/api-load-test.js) to validate improvements against established baselines.
- Built-in Markdown templates ensure every optimization is documented and comparable across CI runs.

## Frequently Asked Questions

### Do I need to modify my application code to use these profiling tools?

No. The majority of tools recommended in [`docs/skills/engineering/performance-profiler.md`](https://github.com/alirezarezvani/claude-skills/blob/main/docs/skills/engineering/performance-profiler.md) run externally. `py-spy` attaches to live PIDs, `clinic` wraps your process, and Go’s pprof endpoints expose data via HTTP without changing business logic. Only the Go implementation requires adding the `net/http/pprof` import, which exposes debug endpoints without affecting runtime behavior.

### What is the recommended load testing tool across all three languages?

**k6** is the standard load-testing tool for Node.js, Python, and Go applications within this skill. The repository provides [`tests/load/api-load-test.js`](https://github.com/alirezarezvani/claude-skills/blob/main/tests/load/api-load-test.js), a JavaScript-based k6 script that works with any HTTP backend, recording latency percentiles and error rates to validate profiling results.

### How do I detect memory leaks in Node.js applications?

Use the `scripts/memory-profile.mjs` utility to measure heap growth before and after forced garbage collection. Run the script with `node --expose-gc` to enable `global.gc()`. If heap usage exceeds the baseline by more than 10% after GC, the skill flags this as a potential leak requiring deeper analysis with `clinic heapprofiler`.

### Can I profile a running Python process without restarting it?

Yes. `py-spy` supports attaching to live processes by PID using the command `py-spy record -o flamegraph.svg --pid <PID> --duration 30`. This reads the Python process memory from `/proc` without requiring code instrumentation or service interruption, making it safe for production environments.