The disk came with me. So did NTFS.

Treat the hardware as a stakeholder. Green checks can still hide a scaling problem, and the cheap fix is usually the one a cloud can wave off.

I have a habit of treating the hardware as a stakeholder, and of not confusing clean, readable code with software that is actually good. A green board can still be late. In the cloud that kind of lateness gets waved off because you can add workers or disk and the job still finishes. Last week I moved the homelab onto a Pi because a ten year old Windows tower would not stay powered on. Uptime was the fire. I knew I had brought the Windows disks with me, and I shipped it anyway.

The TV guide in Jellyfin crawled while several games recorded, college volleyball and other sports with NFL coming, and nothing was down. The status page said OK the way it had been saying OK since the Pi took over, and the guide still took too long to load. The remote felt dead in the living room while the box sat there healthy.

The disks had come with me. I unplugged them from the tower and plugged them into the Pi rather than copy twelve terabytes that weekend, and one of them was still NTFS on USB, about 93 percent full, with Linux reaching it through ntfs-3g. Jellyfin was reading the library and writing DVR on that disk while an hourly snapshot moved files. That snapshot is what the status page pings. A long OK on Hourly Backup is not a slow website. It is the house under load, three writers on one spindle, and the living room felt it before the dashboard had a red row to show.

After the fact, ntfs-3g was taking about ten percent of the CPU for each recording that was landing, and the disk was taking concurrent writes it could not keep up with.

Hourly Backup events. After the change, green OK rows take 3 to 4 seconds. Before that the same check took about 20 seconds, then 1 minute 44 seconds and 2 minutes 30 seconds, still marked OK.

Typical hourly backup GETs were 15 to 24 seconds, with spikes at 1 minute 44 seconds and 2 minutes 30 seconds. After I changed the disk they sit at 3 to 4 seconds. There is a down window on August 30 from about 17:05 to 18:00. The check had been green on the slow rows too. At work I have watched syncs pull a stack of network calls and then filter in the app, instead of filtering at the database, and still get counted as success because they completed. Late used to mean lost revenue. Here it meant that remote.

DVR writes now land on ext4, so Linux is not walking through ntfs-3g on every recording, and the overhead is negligible. The snapshot still runs and the recordings still land, and when the writes got cheap the CPU went idle on those same streams. I did not get a bigger Pi. I got the path cheap enough that the software I already had could run.

I did a version of this on purpose with Conway’s Game of Life, held at 30 ticks a second. A tight loop is a microscope the same way a Pi with no spare watts is a microscope. At that rate you find the badly written loops immediately, even when the code looks clean enough to ship. The shape is ordinary. You walk a list, and on every pass you search another list.

for (const user of users) {
  const account = accounts.find((account) => account.id === user.accountId)
  if (!account?.active) continue
  sendInvoice(user, account)
}

That reads like English. It also does a full scan of accounts for every user. The rewrite does the lookup once, then walks.

const accountsById = new Map(
  accounts.map((account) => [account.id, account]),
)

for (const user of users) {
  const account = accountsById.get(user.accountId)
  if (!account?.active) continue
  sendInvoice(user, account)
}

Both can look like good software in a code review. Only one holds when the cycle gets short. The version I have actually wanted at work is the next step: do not pull the inactive accounts at all, filter at the database, and skip the app-side search. Most web applications have a cycle long enough that you never notice. When the meters go yellow the meeting is about more machines. I like to imagine web applications that do not need their dials turned when that happens.

At homelab scale that is headroom. At work it is money you do not spend on the next box. The tower is still unplugged.