Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Changelog

All notable changes to this project are documented here. The GitHub release of each version uses the matching section.

4.6.2 - 2026-10-20

Changed

  • watch needs a server of version 4.5.0 or newer (/info with connections and scenario). Before, it left out the lines that an older server did not report; now it stops with This server is torchio 4.2.1, and watch needs 4.5.0 or newer. A server newer than watch is read as before.
  • When a command or an option is wrong, the usage is printed on the standard error, after the message, and not on the standard output, so it no longer ends up in a file or a pipe that receives the output of a command. --help, -h and help still print it on the standard output.

4.6.1 - 2026-10-19

Added

  • watch and the control panel have a line for each /memory, /leak, /disk, /fd and /connections that is holding something, with what it holds and the seconds left (/memory: 100 MB, 18 s left), as /cpu already had. /info reports it as secondsLeft in memory, disk, fd and connections (null when nothing is held), the time until the last hold of that resource lets go.

Changed

  • /info reports the limit of descriptors of the process (fd.processLimit, the soft ulimit -n), and the descriptors bar of watch and of the control panel compares with the lower of that and MAX_FD, so it is full when EMFILE comes and not at a quarter of a limit the process can’t reach. watch marks it with (ulimit).

Documentation

  • The site has llms.txt (an index of the pages) and llms-full.txt (all of them in one file) for language models, and a skill for agents that use torchio, at /SKILL.md and in skills/torchio/. The page For AI agents says how to install it.

4.6.0 - 2026-10-19

Added

  • torchio version (also --version and -V) prints the version of the binary, which was only in /info until now. It is in the shell completions.

4.5.0 - 2026-10-19

Added

  • /payload?mb= answers with mb MB of data, streamed and announced with its Content-Length, and POST /payload takes an upload, throws it away and reports its bytes, time and speed (413 over the limit). MAX_PAYLOAD_MB (1024 by default) limits both, and TOKEN protects it. It is for testing the limits on the size of a body and the timeouts of proxies, ingresses and load balancers.
  • /scenario runs a list of steps one after the other, so a test can be repeated without calling the endpoints by hand: POST a JSON list like [{"cpu": 80, "seconds": 60}, {"memory": 500, "seconds": 30}, {"ready": "off", "seconds": 20}], GET to see where it is and DELETE to stop it. The steps are cpu (with workers), memory, disk, fd, connections, ready, block and a pause, with the limits of their endpoints. The whole scenario is checked before it starts, and a wrong step is a 400 that says which. One runs at a time (409), a step that does not fit the budget at its turn stops it with the reason, and TOKEN protects it. /info (scenario), watch and the control panel show it, and the documentation has a page about it.
  • torchio scenario <file|-> [--wait] starts a scenario from a file or stdin and, with --wait, follows it and exits with 0 only if it finished, so a pipeline can run it and go on; torchio scenario status and stop do the other two requests. torchio payload get [mb] downloads and throws the data away, reporting the speed and failing on a body that is cut short, and torchio payload post <file|-> uploads a file or stdin and reports what the server counted. They are in the shell completions, in the reference of the endpoints and in the page Starting a test.
  • The control panel has a card for /payload (download and upload, from the page, with the speed and a body cut short reported), one for /flaky (sends 20 requests and counts the failures) and one for /status/:code. /info reports limits.maxPayloadMb for the sliders. /oom has no card.

Documentation

  • The reference of the endpoints names the command that does the same (torchio cpu [percent] [hold] [workers]), in a column of the table and in the section of each endpoint. It comes from the list of commands the program itself uses, and a test checks that every command calls an endpoint of the catalog.

4.4.0 - 2026-10-19

Added

  • /block?ms= freezes the server: after answering, every thread of the runtime sleeps for ms (up to MAX_BLOCK_MS, 30000 by default), so the process is alive but accepts and answers nothing, to test liveness probes and timeouts. /info (block), the control panel and torchio block [ms] have it, and TOKEN protects it.
  • /oom allocates memory without a budget until the kernel kills the process, to test OOMKilled, the exit code 137 and restart policies. It needs ALLOW_OOM=1 (otherwise it answers 403 and does nothing) and, with TOKEN set, the token. /config shows allowOom.

Changed

  • The installer is also served by the site: curl -fsSL https://torchio.altr.dev/install | sh, which the README and the install page now show. The address on raw.githubusercontent.com keeps working and is the one to use if the site is down; the binary comes from the GitHub release either way.

4.3.0 - 2026-10-19

Added

  • /flaky?rate=&code=&ms= fails rate percent of the requests with code (503 by default) and answers 200 to the rest, to test retries, circuit breakers and outlier detection. ms makes a failing answer wait first, like /delay. torchio flaky [rate] [code] [ms] calls it.
  • /cpu?workers= loads only the first workers and leaves the others idle, to simulate an uneven load across the cores. /info (stress.burn.workers), torchio_cpu_burn_workers, watch and the control panel show how many are loaded. By default it is all of them, as before.
  • /connections?count=&hold= opens TCP connections to the server itself and holds them, with the budget MAX_CONNECTIONS (500 by default, 429 when it does not fit), to test connection limits, load balancers and a shutdown with open sockets. /info (connections), /metrics (torchio_connections_held and torchio_connections_limit), watch, the control panel and torchio connections [count] [hold] have it. Like the other endpoints that change the state, TOKEN protects it.
  • SHUTDOWN_GRACE_SECONDS makes SIGTERM and SIGINT drain before the process ends: the port closes, the requests and connections already open are served, and it ends when none is left or the time is up. A line each second says what is open, /info (shutdown) and /metrics (torchio_draining, torchio_open_requests, torchio_open_connections) report it, and another signal ends it at once. The default 0 ends the process right away, as before, and now says which signal arrived.

Documentation

  • The documentation is a site, at https://torchio.altr.dev, with a page for each part of what used to be the README: the endpoints and their reference (written from the catalog that /help is built from), the command line, watch and the control panel, the configuration, Docker and Kubernetes. It is published with each release.
  • The README is short: the install, the first test and the links to the site. It has a section for each way to install (Docker, Homebrew, the install script, the release binary and the source), and it now fits in Docker Hub whole.

4.2.0 - 2026-10-19

Added

  • /metrics has torchio_http_request_duration_seconds, a histogram of the time taken to answer, by route and status code, with buckets from 5 ms to 60 s.
  • LOG_FORMAT=json writes the logs as one JSON object a line (timestamp, level, message), the lines of /log included, and a line for each request with its method, path, status and duration. The default is still plain text, with no line for each request.
  • The deploy folder has Kubernetes manifests (a Deployment and a Service, with kustomize) and a Helm chart, with the probes, the limits and a non-root container with a read-only filesystem.

4.1.2 - 2026-10-19

Added

  • The Docker image is tagged with the version without the v (X.Y.Z), with the minor (X.Y) and with the major (X), as well as vX.Y.Z and latest.

4.1.1 - 2026-10-19

Changed

  • The completions list serve and watch first, then the commands that start a test, then healthcheck, completions and help.

Fixed

  • The Homebrew formula written by the release made the binary executable too late for the completions to be generated, and brew install failed with EACCES. The formula published for 4.1.0 was corrected in the tap.

Documentation

  • The README says what to check when Tab does not complete in zsh after brew install.

4.1.0 - 2026-10-19

Added

  • torchio serve starts the server, the same as torchio with no command, so the command is in help and in the completions. The Docker image still runs torchio.
  • torchio completions <bash|zsh|fish> prints the completion script of a shell: the commands, their options and the words of ready. The Homebrew formula installs them with the binary.
  • Tab completes the name of a command on the command line of torchio watch.

4.0.0 - 2026-10-19

Changed

  • torchio is rewritten in Rust and ships as a single static binary. The endpoints, parameters, limits, answers, environment variables and metrics are the same.
  • The Docker image is the binary and an empty /tmp, about 1.4 MB, with no shell. It runs as the user 65532, and its HEALTHCHECK runs torchio healthcheck. A directory used as DISK_DIR must be writable by that user.
  • The server needs a few MB of memory instead of about 50, and the memory of /memory and /leak goes back to the OS as soon as it is released.
  • The workers of /stress and /cpu are threads, not processes. /stress is about 1.7 times faster on the same machine: the same number keeps a core busy for less time.
  • WORKERS defaults to the number of CPUs the process can use, which counts the CPU limit of a container (--cpus 2 gives 2 workers). It used to be the number of cores of the machine.
  • watch is a command of the binary: torchio watch, or docker exec -it <container> torchio watch. It speaks plain HTTP only.
  • The help text of torchio_workers says threads instead of processes.

Added

  • torchio healthcheck exits with 0 when the server answers on PORT, for an image that has no wget or curl.
  • torchio cpu 80, torchio memory 512 --hold 60, torchio ready off 30…: a command for each endpoint that changes the state of a server, so a test starts without curl. It takes --url and --token (or TOKEN).
  • torchio watch has a new look on a terminal: smooth bars with a gradient, a header, a readiness badge, lit-up activity and the keys as chips. The plain text of --once, pipes and NO_COLOR is unchanged.
  • On a terminal, torchio watch takes keys that start the tests (c cpu, m memory, x crash…), and : for any command. --read-only turns them off, --token sets the token, and --once or a pipe never take keys.
  • The binary alone for linux/amd64, linux/arm64, macos/amd64 and macos/arm64, with its SHA256SUMS, is attached to each GitHub release.
  • install.sh installs the binary of the latest release for the system (Linux or macOS, amd64 or arm64) after checking its checksum: curl -fsSL https://raw.githubusercontent.com/altrdev/torchio/main/install.sh | sh.
  • brew install altrdev/tap/torchio: the release updates the formula of the Homebrew tap.

3.5.0 - 2026-10-19

Added

  • GET /log?lines=&rate= writes lines to stdout at a given rate, then stops (MAX_LOG_LINES, MAX_LOG_RATE). It needs the token with TOKEN. /info has log while it writes, and watch and the control panel show it.
  • GET /echo returns the request as the server sees it (headers, client address, protocol), with Authorization, Proxy-Authorization and Cookie masked. TRUST_PROXY makes it follow X-Forwarded-*.
  • GET /help lists every endpoint with its parameters, defaults and limits, as JSON or as plain text for a browser. GET /config shows the effective configuration, without the token. Both are open, and /help is built from the same definitions the endpoints read their parameters from (src/endpoints.js).

3.4.0 - 2026-10-18

Added

  • TOKEN: when set, /stress, /cpu, /memory, /leak, /disk, /fd, /ready/off, /ready/on and /crash need Authorization: Bearer <token> and answer 401 without it. /, /ready, /info, /metrics, /delay and /status/:code stay open, so probes and scrapers keep working. /info reports auth, and the control panel asks for the token when it gets a 401. Without TOKEN nothing changes.

3.3.1 - 2026-10-18

Added

  • The control panel has a favicon (the logo). When the server is not ready or can’t be reached, the tab turns red and its title says so, so you can tell from another tab.

3.3.0 - 2026-10-18

Added

  • A control panel in the browser at /ui, turned on with UI=1 (off by default, since it makes /crash a button). It shows what watch shows, with the history of the last 60 seconds, plus the requests by status, the readiness and a card with sliders and buttons for every test. It is one static page: no new dependency, no build.

3.2.0 - 2026-10-18

Added

  • /cpu?percent=&hold=: keeps every worker busy for a share of the time, to hold the CPU at a level for a while (for CPU based autoscalers). percent=0 stops it. It shows in /info (stress.burn), in /metrics (torchio_cpu_burn_percent) and in watch.
  • /leak?rate=&mb=&hold=: memory that grows by itself, rate MB each second up to mb, then is held and released. It uses the budget of /memory.
  • START_DELAY_SECONDS: the port stays closed for that many seconds after the start, to test startup probes and slow rollouts (default 0).

3.1.1 - 2026-10-18

Added

  • watch shows the file descriptors held by /fd (a bar and its history) and the state of /ready, with the seconds left when it is not ready. Against a server older than 3.1 those two lines are left out.

Changed

  • The animation of the terminal view in the README shows the two new lines.

3.1.0 - 2026-10-18

Added

  • /ready, /ready/off?seconds= and /ready/on: a readiness check you can switch to 503 for a while or until you switch it back, while / keeps answering 200. For readiness probes and load balancers.
  • /crash?code=&after=: ends the process with the exit code you choose, to test restarts and backoff.
  • /fd?count=&hold=: opens file descriptors and holds them, to test what happens when a process runs out of them (EMFILE). MAX_FD is the total that can be held at once (default 10000).
  • /info has fd and ready, /metrics has torchio_fd_held, torchio_fd_limit and torchio_ready.

Changed

  • The Kubernetes example uses /ready for the readiness probe.

3.0.1 - 2026-10-18

Changed

  • Documentation: the history of the names in the README and in this changelog was simplified.

3.0.0 - 2026-10-18

Changed

  • Breaking: the project is now called Torchio (it was high-cpu-node before). The Docker image is altrdev/torchio, the package is torchio and the repository is github.com/altrdev/torchio. altrdev/high-cpu-node stays deprecated.
  • Breaking: the Prometheus metrics start with torchio_. process_resident_memory_bytes keeps its name.
  • The name in /info is torchio, and the files of /disk are called torchio-disk-*.

2.5.3 - 2026-10-18

Changed

  • README reorganised to start with what the tool does: a short pitch, the animated terminal view, a 30 seconds try-out and scenarios (OOM kills, autoscaling, probes and timeouts, disk, metrics), followed by the reference.
  • The README no longer shows the logo at the top, since the animation under the pitch does the same job (docs/logo.svg and docs/logo.png stay in the repo).
  • docs/watch.svg is animated: the bars grow and shrink and the history scrolls while a load runs.

2.5.2 - 2026-10-18

Added

  • Tests with node:test (npm test): endpoints and limits, budgets, a crashing worker, an unusable DISK_DIR, the cleanup of the files, the configuration, /metrics and watch.

Changed

  • The code is split into modules under src/ (one file for each endpoint, plus config, parameters, budget, worker pool and metrics). server.js only starts it, so npm start and the Docker image are unchanged. The answers of every endpoint, /info and /metrics are the same.
  • A variable such as WORKERS or MAX_NUMBER that is not a positive integer is reported at startup and replaced by the default, instead of being ignored silently.
  • Shutdown no longer detaches the exit handler of the workers: the pool knows it is stopping.
  • CI runs the tests on Node 22, 24 and 26, fails when CHANGELOG.md has no section for the version in package.json, and validates /metrics with promtool.

Fixed

  • If /memory can’t allocate the buffer, the memory it reserved is given back to the budget.

2.5.1 - 2026-10-18

Changed

  • The README copied to Docker Hub no longer has the badge line, which Docker Hub showed one badge per row.

2.5.0 - 2026-10-18

Added

  • /metrics endpoint: the figures of /info in the Prometheus text format, plus a counter of the requests answered, by route and status code.
  • Banner for the repository social preview (docs/social-preview.svg and docs/social-preview.png).

Changed

  • The README badges are on one line, so Docker Hub shows them in a row.

2.4.1 - 2026-10-18

Fixed

  • cli.js watch: the disk directory is on its own line and shortened from the left, so a long path no longer wraps the free space onto another line.

2.4.0 - 2026-10-18

Added

  • /info endpoint: JSON with the requests in progress, the memory and disk held with their limits, the process memory, the container memory limit and the free disk space.
  • cli.js watch (npm run watch): terminal view of /info with bars and a short history. It also works inside a container with docker exec.

2.3.2 - 2026-10-18

Added

  • Project logo (docs/logo.svg and docs/logo.png), shown in the README.
  • README: status badges, Docker Compose and Kubernetes examples, security note.

Changed

  • npm run dev uses node --watch instead of nodemon, which is no longer a dependency.

2.3.1 - 2026-10-18

Changed

  • The changelog moved from the README to this file.
  • A GitHub release is created for every tag, using the matching section of this file as notes.

2.3.0 - 2026-10-18

Added

  • /delay endpoint: answers after ms milliseconds without blocking the server.
  • /status/:code endpoint: answers with the requested HTTP status (200-599).
  • /memory endpoint: allocates mb megabytes and holds them for hold seconds.
  • /disk endpoint: writes mb megabytes to a file in DISK_DIR and deletes it after hold seconds.
  • MAX_DELAY_MS, MAX_MEMORY_MB, MAX_DISK_MB, MAX_HOLD_SECONDS and DISK_DIR environment variables.

Changed

  • README restructured with a section per endpoint.
  • CI runs the built Docker image and checks the endpoints and the healthcheck.

2.2.1 - 2026-10-18

Changed

  • The image altrdev/high-cpu-node is deprecated, and this is its last release.

2.2.0 - 2026-10-18

Changed

  • Updated to Express 5, the node:26-alpine base image and cors 2.8.6.

2.1.0 - 2026-10-18

Added

  • HEALTHCHECK in the Docker image.
  • The Docker Hub description is synced from the README on release.

2.0.0 - 2026-10-17

Added

  • Worker pool, one process per core, with automatic restart of crashed workers.
  • PORT, WORKERS and MAX_NUMBER environment variables.

Changed

  • Breaking: /stress rejects a number outside 0..MAX_NUMBER with a 400 (it was unbounded).