Devlog · ops
The first visitor should not pay the cold start
Identified GETs, no body, no credentials — a systemd user timer that knocks on the origin every ten minutes so Next.js is already there.
PeerWeave’s public site is a Next.js app on Render. This personal site is not. lucastilford.com is a static tree: HTML, CSS, and JavaScript at the repo root, published for free, with an empty build command. Static files do not idle. A web service on Render Free does.
After fifteen minutes with no inbound HTTP, Render drops the Free instance. The next person to open peerweave.com does not get the app. They get “Welcome to Render / APPLICATION LOADING” for half a minute to a minute and a half while the origin boots. That is a tax on curiosity. I would rather the site already be standing.
So the hub PC — the same always-on Linux box that can also run
Manticore Network Intelligence on networks I own — now knocks.
The keep-warm job is not in manticore-net. It lives in the PeerWeave repo at
deploy/keep-warm/.
A daemon, in the old sense
I wrote once about daemons as unseen agents that convert information into order. This is a small one. Every ten minutes (plus a little jitter so it is not a metronome) it GETs three URLs with an identified User-Agent:
https://www.peerweave.com/— the visitor landing pagehttps://www.peerweave.com/app— the web client-
https://peer-weave.onrender.com/— the Render origin, so a future Cloudflare cache hit cannot skip the machine that actually sleeps
No POST. No cookies. No credentials. If Render’s interstitial comes back anyway, the script retries with backoff until real Next.js HTML arrives, with a ninety-second ceiling per attempt. The loop floor is five minutes, so it cannot hammer the site even if someone edits the interval down.
hub PC (systemd --user timer, Linger=yes)
│
│ GET every ~10 min
▼
www.peerweave.com/ ─┐
www.peerweave.com/app ├─ Cloudflare (maybe)
peer-weave.onrender.com/ ─┘
│
▼
Render origin (the process that idles)
Why the timer lives on this machine
GitHub Actions can ping the same three URLs. The workflow is
.github/workflows/keep-warm.yml, scheduled every ten minutes. GitHub’s cron
can lag past fifteen minutes. When it lags, the origin is already asleep and the Action is
just another cold-start visitor. The hub-PC timer is the real keep-alive. The Action is a backup, and it
only runs after that workflow is on main.
The installer copies the script to ~/.local/bin/peerweave-keep-warm and enables a systemd
user timer. loginctl enable-linger is set so the timer keeps firing after
logout. Persistent=true means a missed tick after a reboot still runs. It is not a packet capture. It is
not a health dashboard. It is a polite knock.
A live probe after install: all three URLs returned 200 in well under a second. That is the whole point — visitors should see that, not the boot screen.
The caveat that actually matters
PeerWeave’s render.yaml already asks for Starter, which does not idle. If
people still see the boot page, the live service is on Free. Keep-warm is the workaround.
Starter is the durable fix.
A Free instance kept awake uses most of the 750 monthly instance hours. That is the honest cost of this trick: you have not escaped the meter; you have chosen to spend the hours on availability instead of on sleep. When the product should be up for strangers, pay for a plan that does not nap.
This page is hosted the other way: static files on the same Render product that does not spin down, at the price of zero dollars. The operator notes — commands, knobs, what to stop — live next to this log.