09 · Process Manager
An HTTP server on port 4000 that deliberately crashes on every 30th request, so you can watch 3va’s supervisor bring it back. You don’t need pm2.
Source: examples/09-process-manager
Start
cd examples/09-process-manager
3va start server.js --name demo-api ✓ Started process 'demo-api' (supervisor PID 3137986, 1 instance(s))
Logs: ~/.3va/processes/demo-api.log3va status demo-api Name PID Status Restarts Inst Entry
-------------------- -------- -------- ---------- ------ --------------------
demo-api 3137986 running 0 1 server.jscurl localhost:4000 # {"pid":3138021,"uptime":"2.0s","requestCount":1}Watch it restart
for i in $(seq 1 31); do curl -s localhost:4000; echo; doneRequest 30 kills the worker, so it gets an empty reply, and so does any
request that arrives while the worker is down. About half a second later a
new worker is up with a new PID and requestCount back at 1:
3va logs demo-api[worker] listening on :4000 (pid 3138021)
[ERROR] Simulated crash after request #30
[worker] listening on :4000 (pid 3138739)3va status now shows Restarts: 1.
Manage it
3va status # every managed process
3va logs demo-api --lines 200
3va restart demo-api
3va stop demo-api # SIGTERM, then SIGKILL if still alive after 30 s
3va delete demo-api # stop + remove metadata and logsHow it works
-
3va startforks a supervisor and returns. The supervisor runs your script as a child and restarts it on crash with exponential backoff: 500 ms → 1 s → 2 s → … capped at 30 s. It gives up after 15 consecutive crashes (--max-restarts). -
The state lives in
~/.3va/processes/<name>.json(entry, cwd, PIDs, restart count, flags) with logs next to it in<name>.log. -
There are no
--allow-*flags on3va start. A managed process gets its permissions frompackage.json, so they’re recorded in the repo, not lost in someone’s shell history:package.json{ "3va": { "no-prompt": true, "permissions": { ".": { "allow-net": ["*"] } } } }
Things to keep in mind
-
--portgrantsPORT, and onlyPORT.3va start --port 4001setsPORTfor the process and also allows the script to read that one variable, so the server moves to 4001 with noallow-envinpackage.json. Any other configuration you pass through environment variables (DATABASE_URL,NODE_ENV, …) still needs an explicit grant. Without one, the variable just looks unset and you get no error:".": { "allow-net": ["*"], "allow-env": ["DATABASE_URL"] } -
"allow-net": ["*"]is broad. For a server that only listens, any network grant is enough to bind (see 02). Use*only if the process also makes outbound calls to hosts you can’t list. -
Crashes are visible only in the logs. Requests in flight during a crash and the ~500 ms restart window fail. Use
--instances N(load-balanced withSO_REUSEPORT) if you need to stay available while one worker restarts. -
In a container, use
--attach. It keeps the supervisor in the foreground so it can be PID 1. The default daemon mode forks and exits, which would end the container. -
--no-autorestartmakes a crash final.3va statusthen showserroruntil you run3va restart. -
Process names are global per user (
~/.3va/processes/). Two projects that both use--name apiwill collide. -
See Process Manager for the full reference.