← All posts

SQLite

Aug 14, 2026
August 14 - ten readiness gates instead of one number
A single readiness percentage is a number you can fool yourself with. Waypoint replaced it with ten independent gates that each pass or fail on their own evidence.
Aug 9, 2026
August 9 - treating the listing database as a cache, not the record
Listing sites edit and pull their own pages. Homestead keeps every capture as immutable evidence and rebuilds the searchable database from it, so a delisted house keeps its record.
Aug 9, 2026
August 9 - a green unit that produced no backup for three days
The timer that snapshots Loupe's databases reported success while the newest snapshot in the destination was three days old. Two scheduled runs had failed and a manual test run had overwritten the status. Then a real restore drill, which checked four properties and first failed on my own script's assumption.
Aug 8, 2026
August 8 - the price field that looked like history and wasn't
Breadcrumbs grew a price-history service over 17 months of my own grocery orders. Two facts about the data shaped the whole design, a passing test suite hid a false alert that only a replay against real orders exposed, and raising the threshold provably could not fix the promo problem.
Jul 27, 2026
July 27 - two background workers, one status column, and a system that never converged
Prospect's two AI background workers were quietly overwriting each other's status, so every service restart redid work that was already done. The handoff called it a one-row cosmetic cleanup. Reading the two workers against each other showed something worse, and the fix cost no GPU time.
Jul 27, 2026
July 27 - the migration command that defaulted to production
Prospect's migration runner picks the live database when you forget to tell it otherwise. I found that out by running it without the environment variable, against production.
Jul 24, 2026
July 24 - three backups, zero bytes, and a mount that timed itself out
Three database backups written to network storage two weeks earlier were all zero bytes. The cause was an idle timeout on the mount tearing it down mid-write. The obvious retry then failed instantly for a second, unrelated reason, and the worker stopped and asked instead of improvising.
Jul 19, 2026
July 19 - two rankings that cannot be compared, and a duplicate detector allowed to be wrong
Prospect got meaning-based search fused with its keyword search, and a semantic check for reposted listings. Both had to be designed so they could fail without taking anything down, and the duplicate threshold was calibrated on a copy before it touched the real database.
Jun 21, 2026
June 21 - glass on the surface, plumbing underneath
A wide day: shipped a dormant glass redesign and a fully responsive header, chased a stats box that kept clipping, traced six photo-pairing mis-binds down to a filename suffix, sorted out the faithful way to pull edited photos, relocated my notes vault, and ran a security review I'm keeping vague on purpose.
Jun 20, 2026
June 20 - a portable enrichment import, a console that runs the pipeline, and a brand pinned down
A long, many-threaded day. I built the full path that lets a second person's Apple-photo metadata become my app's enrichment database, turned the setup console into something that can actually start the pipeline stages itself, split the frontend out of the monolith, unified the brand across app and marketing site, stood up real email, and fixed a couple of bugs that had been silently breaking the photo pipeline for a while.
Jun 19, 2026
June 19 - the day Loupe got its name, its face, and its front door
A long, many-threaded day: renamed both repos to loupe, shipped the Map and Cutting Room pages, built the in-app People view on top of face embeddings, redrew the brand mark down to the favicon, and stood up the onboarding front door.
Jun 17, 2026
June 17 - making Loupe leave my box: portability, a brand, and a public site
The day Loupe stopped being a thing that only runs on my machine. I reframed it as a self-hostable product, made the pipeline portable through environment variables, scrubbed both repos clean for publishing, finalized a brand and header, fixed the photobook's repetition problem, and registered loupeculling.com for a marketing site.
Jun 16, 2026
June 16 - a kernel reboot, two apps becoming one, and an enrichment layer pulled from Apple
The day the project got a name and a spine: I came back to a box that had silently rebooted, merged two sibling photo-review apps into one managed service called Loupe, added a cloud backup and AI-written period summaries, and built an enrichment layer that joins Apple's own labels, people, and scores back onto my library by UUID.
Jun 15, 2026
June 15 - the 462 GB move that took 0.09 seconds, and two review tools
A long day: turning a 462 GB copy into an instant rename by understanding the filesystem, catching two backup processes about to trample each other, and building two browser tools to actually review ~91,000 photos without ever deleting one by accident.
Jun 14, 2026
June 14 - a dependency cascade, and matching files back to a list
An aggressive package cleanup quietly broke my storage box's admin UI through a dependency I didn't know mattered. Then a filename-normalizer bug taught me to trust byte sizes over names when matching files back to a database.
Jun 12, 2026
June 12 - culling rules that find nothing, and a bucket that wasn't what it looked like
With the metadata database built, I started defining rules to surface delete-candidates. Two of the rules found nothing, one was secretly broken, and the biggest 'junk' bucket turned out to be footage I'd never delete. The lesson of the day: rules lie, pixels don't.
Jun 9, 2026
June 9 - building a photo-metadata pipeline with no sudo and a flaky network
Day one of the photo project: build an ingest tool that reads ~91,000 photos and videos into a SQLite database so I can cull systematically. The build went fine. The environment fought me, and the performance lessons were not where I expected.