Home All posts →

PocketBill Blog

The Process I Thought I'd Killed

Published 2026-10-09 · PocketBill team

Restarting an app is a lie when the old process is still alive. A WebSocket broker allows one connection per client id, a cache keeps handing back expired tokens, and the symptom always looks like 'the network is broken'. PocketBill skips this entire class of bug by having nothing to fight over.

The prices that stopped refreshing

Last week I opened PocketBill to log a subscription and the price quote panel I keep on the second monitor had gone quiet. I restarted everything the way I always do, and the numbers froze at the same value. My first thought was that the network was down, because that is what it always looks like.

It wasn't the network. The process I had "restarted" was never actually gone. On Windows, asking a process to stop politely only stops the one you pointed at — it does not walk down into the children that server had spawned. So the old backend was still sitting there, still holding the port, and the new one came up underneath it looking confused and half-fed.

One identity, one connection

The second half of the problem was stranger. My quote connection points at a broker SDK that allows exactly one live WebSocket per client id. The dead process was still holding that one connection, so the new process got refused, or got a partial feed that looked alive and kept showing yesterday's price.

There is a tidy generalisation in here: anything keyed to an identity — a port, a socket, a login — can only have one owner at a time, and the failed second owner will almost always report it as a connection problem rather than as an ownership problem.

The cache that remembered dead tokens

The same evening I found a smaller cousin of the same bug. The SDK keeps an access token in a cache file, and it refreshes it when it has expired. But once a dead token gets written into that cache, every future start reads it, fails, and looks like a brand-new bug on a brand-new day.

So I added a rule that has nothing to do with networking: expired state must never be written back to disk. Not the token, not the session, not the cached response. The rule isn't clever, it just means tomorrow's me isn't debugging yesterday's corpse.

Why PocketBill stays boring

This is exactly the class of bug PocketBill was built to not have. There is no server, no account, no client id, no socket — nothing for a second copy of the app to fight with. The subscription I log lives on the device I logged it on, and nothing else can hold a stale claim on it.

The trade is real and I don't pretend otherwise: I can't open it on my laptop and see what I recorded on my phone. What I get back is that "I restarted it and it silently broke" simply cannot happen, which for something as boring as a bill tracker is the trade I want.

Kill the tree, not the leaf

The fix that finally worked was stopping the whole tree instead of the one process in front of me, and then giving exactly one script the job of starting and stopping it. If something looks broken right after a restart, check first whether the old version ever died.

Two questions now sit at the top of every one of these evenings. Is the thing you thought was gone actually gone? And is anything expired silently being written back as if it were fresh? Both of them are cheaper to ask than to answer at midnight.

indie-devdebuggingwindowslocal-firstpocketbill
Track it once, see it forever.
Add your first subscription or expense in PocketBill — no account required.