Dan Matthew

Writing · 6 Sep 2026

Photograph once, reprocess forever

The albums are old and fragile, so the collection is photographed one time and never handled again. Everything the public site knows is reprocessed from those photographs and a log of facts.

#stamps #architecture #data #honest software #side project

The albums are older than this project by two decades. Some of the paper is fragile, some of the mounts have perished, and every time I open one I am spending a small amount of a thing I cannot get back. The last system I wanted to build was one that made me handle them twice.

So the rule became: photograph once, and never touch the physical album again. Everything after that is reprocessing over the photographs.

Three layers, one direction

The whole collection is three layers, in order, and the data only ever flows one way.

The first layer is the evidence log: the photographs, and the append-only assertions from the last post. This is the ground truth. It is written once and only ever added to. If everything else burned down, this is what I would rebuild from.

The second layer is an index. It is a working database that is a pure function of the evidence log, and it exists only to make things fast to query. It is disposable. I can delete it and rebuild it from the log, and I do exactly that, on purpose, to prove I still can.

The third layer is the projection: the few kilobytes of honest facts that the public site actually reads, derived from the layers beneath it. Nothing private is in it. No scans, no prices, no storage location, no working notes.

Evidence log photographsplus assertions Index rebuilt fromthe log Projection a few kilobyteshonest facts only Public page a static fileat the edge publish boundary The arrows point one way. The public side never reaches back into the private archive.
⤢ Enlarge

The boundary is a shape, not a rule

The property I care about most is that the arrows only point one way. The public read path can never reach back into the private archive. The public site is a static file sitting at the edge. There is no server behind it a visitor can prod, no database a crawler can wake, no route from a public request to a private photograph.

That separation is not a permission I remember to set. It is the shape of the pipe. The private bytes and the public bytes live in different places, and only a deliberate publish step copies the small honest subset across. If I want to be sure a private scan can never leak, the strongest version of that is not a check. It is having no path at all.

Why reprocess forever earns its keep

Because the log is ground truth and everything above it is derived, I can improve how I read the collection without re-photographing anything. A better detector, a corrected identification, a kind of fact I did not model on day one: all of it is a reprocessing pass over photographs I already have. The physical album is finished being handled the moment I photograph it. The understanding is never finished.

The cost is that the projection can change. A number that was a candidate becomes confirmed. A naive early reading gets superseded by a better one. If you assume your derived data is stable, this design breaks you. So the projection is built to be thrown away and rebuilt, and the public page is written to render whatever honest subset it is handed today, including almost nothing. A page that assumes it will always have data is a page that crashes the first time the truthful answer is "we do not know yet."

What it costs me

Rebuilding the index from the whole log gets slower as the log grows, and I will have to care about that eventually. And "reprocess forever" is really a promise that the record format holds up for decades, which is a promise I can only partly keep. I version the records, I keep the raw photographs, and I try hard not to be clever, because clever formats are the ones you cannot read in ten years.

The last thing a stamp page needs is a picture. A modern stamp design is copyrighted, so I am not allowed to show you the real one. The next post is how the illustrations get drawn instead.