Back to Feed
article 3m read

Status check reread the whole archive just to ask if anything was left

The readiness checks on my store-data archive scaled with years of history. I switched them to a receipt the writer already kept, small indexes over only the backlog, and a heads table for current stock, then gave the deploy script a longer timeout, and I list where the cheaper checks can still lie.

Article DepthPractice

Flow

What each check reads now

Cost now follows the work still waiting, not the size of the archive.

  1. 1Line rows

    Before: every stored record, recounted. After: only records whose done flag is still false.

  2. 2Repair backlog

    Before: a scan of all history. After: a small index of old-format rows, with the version written into the query.

  3. 3Current stock

    Before: open rows dug out of a year of versions. After: the heads table, joined to current versions.

  4. 4Deploy check

    Before: a short fixed wait. After: a named setting with a longer default.

Every sale and delivery the archive had ever stored got reread each time its status check asked "is anything left to do?" The bigger the archive got, the more that one question cost.

The archive keeps every version of what my stores' sales system reports. It never overwrites. It only adds. A status page runs checks on top of it, and my deploy script asks that page whether a new release is healthy. So the page runs a lot, and when it's slow, deploys wait.

I reworked three of those checks in about an hour, then gave the deploy script more patience. I don't have timings to show. This is from the code changes and tests, and the "why" is my own reading.

A check that ignored its own receipt

One check makes sure every sale has been split into line rows, so search can find single items. The old version opened every stored record and recounted its items. Every record, every call.

But each record already had a done flag, set at the same moment its line rows were written. The check just never looked at it. The change was a cheaper count.

It counts the records still marked not done, with an index that holds only those records.

When things are healthy, that index is nearly empty, so the check is nearly free. When work piles up, the cost grows with the pile, which is what you want. The alert means the same thing as before, and a new test forces one sale back to not done and checks that the alert fires.

A number the planner couldn't see

A repair job hunts for rows stored under an older timestamp format. That search scanned all of history. Now a small index covers only the old rows, and the query writes the version number straight into the SQL instead of passing it in. My guess is that Postgres needs to see the number to know the small index applies. That's only safe because the number is my own constant.

"Current" was a needle in a year of hay

Another check compares two views of current stock. Finding "current" meant digging for open rows in a year of old versions. The first try added an index. Minutes later, the next change started from the heads table instead, which already points at each item's current version.

The script that gave up too early

The deploy script quit its status call after a short fixed wait. Now the wait is a setting with a much longer default, and a bad value gives an error that names the setting. That avoids failing a good release, but a stuck page can now hold a deploy longer.

Where it can still lie to me

The check is now only as honest as that done flag. If something ever sets it without writing the line rows, the page says healthy while search is missing data, and nothing I have would catch it.

Keep reading

Pick up a connected idea or branch into a nearby one.

5 paths forward