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
watchneeds a server of version 4.5.0 or newer (/infowithconnectionsandscenario). Before, it left out the lines that an older server did not report; now it stops withThis server is torchio 4.2.1, and watch needs 4.5.0 or newer. A server newer thanwatchis 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,-handhelpstill print it on the standard output.
4.6.1 - 2026-10-19
Added
watchand the control panel have a line for each/memory,/leak,/disk,/fdand/connectionsthat is holding something, with what it holds and the seconds left (/memory: 100 MB, 18 s left), as/cpualready had./inforeports it assecondsLeftinmemory,disk,fdandconnections(nullwhen nothing is held), the time until the last hold of that resource lets go.
Changed
/inforeports the limit of descriptors of the process (fd.processLimit, the softulimit -n), and the descriptors bar ofwatchand of the control panel compares with the lower of that andMAX_FD, so it is full whenEMFILEcomes and not at a quarter of a limit the process can’t reach.watchmarks it with(ulimit).
Documentation
- The site has
llms.txt(an index of the pages) andllms-full.txt(all of them in one file) for language models, and a skill for agents that use torchio, at/SKILL.mdand inskills/torchio/. The page For AI agents says how to install it.
4.6.0 - 2026-10-19
Added
torchio version(also--versionand-V) prints the version of the binary, which was only in/infountil now. It is in the shell completions.
4.5.0 - 2026-10-19
Added
/payload?mb=answers withmbMB of data, streamed and announced with itsContent-Length, andPOST /payloadtakes an upload, throws it away and reports its bytes, time and speed (413over the limit).MAX_PAYLOAD_MB(1024by default) limits both, andTOKENprotects it. It is for testing the limits on the size of a body and the timeouts of proxies, ingresses and load balancers./scenarioruns a list of steps one after the other, so a test can be repeated without calling the endpoints by hand:POSTa JSON list like[{"cpu": 80, "seconds": 60}, {"memory": 500, "seconds": 30}, {"ready": "off", "seconds": 20}],GETto see where it is andDELETEto stop it. The steps arecpu(withworkers),memory,disk,fd,connections,ready,blockand a pause, with the limits of their endpoints. The whole scenario is checked before it starts, and a wrong step is a400that says which. One runs at a time (409), a step that does not fit the budget at its turn stops it with the reason, andTOKENprotects it./info(scenario),watchand 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 with0only if it finished, so a pipeline can run it and go on;torchio scenario statusandstopdo 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, andtorchio 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./inforeportslimits.maxPayloadMbfor the sliders./oomhas 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 forms(up toMAX_BLOCK_MS,30000by default), so the process is alive but accepts and answers nothing, to test liveness probes and timeouts./info(block), the control panel andtorchio block [ms]have it, andTOKENprotects it./oomallocates memory without a budget until the kernel kills the process, to testOOMKilled, the exit code137and restart policies. It needsALLOW_OOM=1(otherwise it answers403and does nothing) and, withTOKENset, the token./configshowsallowOom.
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=failsratepercent of the requests withcode(503by default) and answers200to the rest, to test retries, circuit breakers and outlier detection.msmakes 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,watchand 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 budgetMAX_CONNECTIONS(500by default,429when it does not fit), to test connection limits, load balancers and a shutdown with open sockets./info(connections),/metrics(torchio_connections_heldandtorchio_connections_limit),watch, the control panel andtorchio connections [count] [hold]have it. Like the other endpoints that change the state,TOKENprotects it.SHUTDOWN_GRACE_SECONDSmakes 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 default0ends 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
/helpis built from), the command line,watchand 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
/metricshastorchio_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=jsonwrites the logs as one JSON object a line (timestamp,level,message), the lines of/logincluded, 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
deployfolder 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 asvX.Y.Zandlatest.
4.1.1 - 2026-10-19
Changed
- The completions list
serveandwatchfirst, then the commands that start a test, thenhealthcheck,completionsandhelp.
Fixed
- The Homebrew formula written by the release made the binary executable too late for the completions to be generated, and
brew installfailed withEACCES. 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 servestarts the server, the same astorchiowith no command, so the command is inhelpand in the completions. The Docker image still runstorchio.torchio completions <bash|zsh|fish>prints the completion script of a shell: the commands, their options and the words ofready. 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 user65532, and itsHEALTHCHECKrunstorchio healthcheck. A directory used asDISK_DIRmust be writable by that user. - The server needs a few MB of memory instead of about 50, and the memory of
/memoryand/leakgoes back to the OS as soon as it is released. - The workers of
/stressand/cpuare threads, not processes./stressis about 1.7 times faster on the same machine: the samenumberkeeps a core busy for less time. WORKERSdefaults to the number of CPUs the process can use, which counts the CPU limit of a container (--cpus 2gives 2 workers). It used to be the number of cores of the machine.watchis a command of the binary:torchio watch, ordocker exec -it <container> torchio watch. It speaks plain HTTP only.- The help text of
torchio_workerssays threads instead of processes.
Added
torchio healthcheckexits with0when the server answers onPORT, for an image that has nowgetorcurl.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 withoutcurl. It takes--urland--token(orTOKEN).torchio watchhas 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 andNO_COLORis unchanged.- On a terminal,
torchio watchtakes keys that start the tests (ccpu,mmemory,xcrash…), and:for any command.--read-onlyturns them off,--tokensets the token, and--onceor a pipe never take keys. - The binary alone for
linux/amd64,linux/arm64,macos/amd64andmacos/arm64, with itsSHA256SUMS, is attached to each GitHub release. install.shinstalls the binary of the latest release for the system (Linux or macOS,amd64orarm64) 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 withTOKEN./infohaslogwhile it writes, andwatchand the control panel show it.GET /echoreturns the request as the server sees it (headers, client address, protocol), withAuthorization,Proxy-AuthorizationandCookiemasked.TRUST_PROXYmakes it followX-Forwarded-*.GET /helplists every endpoint with its parameters, defaults and limits, as JSON or as plain text for a browser.GET /configshows the effective configuration, without the token. Both are open, and/helpis 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/onand/crashneedAuthorization: Bearer <token>and answer401without it./,/ready,/info,/metrics,/delayand/status/:codestay open, so probes and scrapers keep working./inforeportsauth, and the control panel asks for the token when it gets a401. WithoutTOKENnothing 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 withUI=1(off by default, since it makes/crasha button). It shows whatwatchshows, 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=0stops it. It shows in/info(stress.burn), in/metrics(torchio_cpu_burn_percent) and inwatch./leak?rate=&mb=&hold=: memory that grows by itself,rateMB each second up tomb, 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 (default0).
3.1.1 - 2026-10-18
Added
watchshows 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 to503for a while or until you switch it back, while/keeps answering200. 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_FDis the total that can be held at once (default10000)./infohasfdandready,/metricshastorchio_fd_held,torchio_fd_limitandtorchio_ready.
Changed
- The Kubernetes example uses
/readyfor 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-nodebefore). The Docker image isaltrdev/torchio, the package istorchioand the repository isgithub.com/altrdev/torchio.altrdev/high-cpu-nodestays deprecated. - Breaking: the Prometheus metrics start with
torchio_.process_resident_memory_byteskeeps its name. - The
namein/infoistorchio, and the files of/diskare calledtorchio-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.svganddocs/logo.pngstay in the repo). docs/watch.svgis 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 unusableDISK_DIR, the cleanup of the files, the configuration,/metricsandwatch.
Changed
- The code is split into modules under
src/(one file for each endpoint, plus config, parameters, budget, worker pool and metrics).server.jsonly starts it, sonpm startand the Docker image are unchanged. The answers of every endpoint,/infoand/metricsare the same. - A variable such as
WORKERSorMAX_NUMBERthat 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.mdhas no section for the version inpackage.json, and validates/metricswithpromtool.
Fixed
- If
/memorycan’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
/metricsendpoint: the figures of/infoin 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.svganddocs/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
/infoendpoint: 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/infowith bars and a short history. It also works inside a container withdocker exec.
2.3.2 - 2026-10-18
Added
- Project logo (
docs/logo.svganddocs/logo.png), shown in the README. - README: status badges, Docker Compose and Kubernetes examples, security note.
Changed
npm run devusesnode --watchinstead ofnodemon, 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
/delayendpoint: answers aftermsmilliseconds without blocking the server./status/:codeendpoint: answers with the requested HTTP status (200-599)./memoryendpoint: allocatesmbmegabytes and holds them forholdseconds./diskendpoint: writesmbmegabytes to a file inDISK_DIRand deletes it afterholdseconds.MAX_DELAY_MS,MAX_MEMORY_MB,MAX_DISK_MB,MAX_HOLD_SECONDSandDISK_DIRenvironment 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-nodeis deprecated, and this is its last release.
2.2.0 - 2026-10-18
Changed
- Updated to Express 5, the
node:26-alpinebase image andcors2.8.6.
2.1.0 - 2026-10-18
Added
HEALTHCHECKin 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,WORKERSandMAX_NUMBERenvironment variables.
Changed
- Breaking:
/stressrejects anumberoutside0..MAX_NUMBERwith a400(it was unbounded).