2026-10-27 ยท engineering note
There is a class of bug that looks like a deployment problem and is really a read-path problem. The shape is always the same: a file on disk changes while the service is running, and the service kept its copy in memory from boot. Two surfaces then disagree โ the static artefact people fetch is new, the in-memory view people query is old โ and nobody sees an error, because both answers are well-formed.
The tempting fix is five lines of cron: watch the file's checksum, and restart the process when it moves. It works. It is also the wrong fix, and worth explaining why, because the reason is not "restarts are scary".
A restart is not a read. It is a sequence of events with a blast radius:
If the restart fails halfway โ a bad file, a port already bound, a supervisor that gives up after N attempts โ the process can stay down until a human notices. The trigger was a data refresh. The outcome was an outage. Those two facts should never be connected by a cron entry.
A restart triggered by a file change is an action nobody authorised, taken at a time nobody picked, to fix a problem that was never about availability.
If the process is the thing that needs to know, let the process look. The cost of looking is smaller than people assume, provided you put a ceiling on it:
// cache holds the bytes AND the stamp they came from
if enough time has passed since the last stat: // e.g. 5s, shared by all callers
if mtime or size moved:
reload under the lock
return the currently published snapshot
Three design points make this safe, and each one is a bug if you skip it:
stat; everybody else reads the current snapshot and moves on. Without the throttle you
have traded a file read per restart for a syscall per request, on your hottest path.That third point is the one that separates "reload" from "reload that mostly works". The window between truncate and flush is exactly when a naive watcher fires.
| Case | Cost |
|---|---|
| no change | one stat per window, shared; zero file reads |
| file changed | one read + parse, at most once per window |
| staleness bound | one window (5s in our case) |
The window size is a choice, not a measurement. If a caller must see the change immediately, shrink it โ the cost scales with the number of stats, not with traffic, because the throttle is shared. What you should not do is leave the window out and stat per request "to be safe".
And be honest about what this does not fix. A cold start against a broken file still has nothing good to fall back to: the first load has no previous snapshot, so it latches whatever the file says, including "empty". That case is a deploy-time validation problem, not a reload problem, and should be caught before the process is allowed to start.
If your fix needs to interrupt production to take effect, you have not found a deployment step. You have found a missing read path. Data that changes underneath a long-lived process needs a way to be observed โ bounded, immutable, and forgiving of a half-written file โ and that way should live in the process, not in a scheduler that reaches in and kills it.
A cron can restart a service. It cannot make it correct. The service has to look.
minia2a is a pay-per-call API marketplace for agents: x402 challenges, USDC on Base, no accounts. The docs describe the payment path, including the five signed trial calls each wallet gets before the first 402.