archive
every post, oldest to newest, with what each year was actually about
thirty-odd posts in reverse-chronological order is a feed, not an archive. this is everything, on one page, with a line about what each year was actually for.
if you want a route through the ideas rather than the dates, start here . if you want one subject collected in one place, topics .
a note on the dates, since they would otherwise flatter me. most of the 2024–2025 posts were written in one long stretch in july 2026, reconstructing work i had already done, and dated to when the work happened rather than when i got round to writing it up. the code, the bugs and the decisions are real and contemporaneous; the prose is not. i would rather say that here than let a tidy publication history imply a discipline i did not have.
2026 · 19 posts
the split. not leaving go — splitting the stack : go for the services that have to be boring, rust for the tools that have to be fast. most of the year is those tools, plus the infrastructure underneath them, and partway through it i retract the testing post i wrote in 2024. that retraction is the most honest thing on this site.
- never let the client tell you who owns it
18 jan
the create endpoint read OwnerID off the request body — stamping it from the session instead, and why a field you validate is still a field you trusted - my production build was 46 releases behind and nothing failed
04 jan
cloudflare pages built this site with hugo 0.118 while i developed on 0.164 — and the config key i added to fix a bug was silently ignored for two days - i said i quit testing. then i shipped seven things.
16 jan
a year ago i declared testing a waste of time for solo devs. then a silent bug ate 79% of my data. an honest retraction. - verifactu in go: a sha-256 hash chain is spain's answer to invoice fraud
08 jan
implementing spain's anti-fraud e-invoicing as an append-only chained-hash ledger, modelled in the pure domain layer - docker stack deploy silently dropped my command (and 3 other swarm lies)
22 jan
compose-spec keys that `docker compose config` renders but `docker stack deploy` quietly ignores — and how to catch them - one schema crate, two analyzers: bilingual full-text search with embedded tantivy
15 jan
embedding tantivy for a latin/greek/spanish corpus — a shared schema crate, language-specific analyzers, and the by-name tokenizer coupling that fails silently - two databases, one binary: duckdb for reads, sqlite for state
08 jan
a polyglot-persistence split for a small analytics service — columnar duckdb for events, row sqlite for state, and a non-blocking batch-insert buffer - brute-forcing the pit window: when 'just try them all' is the right call
01 jan
an exhaustive search over every pit lap and compound to pick a race strategy — why brute force beats a clever heuristic at this scale, and the r-squared-as-confidence wart - a query language in ~1000 lines: lexer, parser, evaluator
25 jan
hand-rolling a log filter dsl in rust — tokenizer, recursive-descent parser, tree-walking evaluator, and when not to reach for a parser generator - don't let your backtest lie to you: leakage guards for a solo research codebase
18 jan
content-addressed model provenance, strict temporal splits, and family-wise error control — the discipline that stops a research backtest from p-hacking itself - clean and verified are different claims: a two-axis trust state machine in postgres
11 jan
modelling 'may we publish this' and 'how faithful is this text' as two orthogonal postgres columns, with check constraints as a structural backstop - cookieless analytics: how a rotating daily salt kills the consent banner
04 jan
identify visitors with a rotating sha-256 hash instead of a cookie — and skip the consent banner by never holding personal data - hand-rolling ols regression in rust, and the collinearity trap that ate my coefficients
27 jan
multiple linear regression from scratch — normal equations, cramer's rule, and the identifiability bug a singular-matrix guard turned into an honest None - rust + wasm canvas2d charts with zero javascript libraries
20 jan
rendering charts in the browser straight from rust on canvas2d — and the static-mut wart edition 2024 caught - welford's algorithm and why i never store the samples
13 jan
computing a rolling z-score over gigabytes of logs in constant memory — online variance, and three detectors combined by max - multi-tenant isolation is a security boundary, not a query filter
06 jan
a payload multi-tenant saas, the privilege-escalation hole hiding in the plugin defaults, and proving isolation with real integration tests - building three mcp servers in rust with rmcp
30 jan
one cargo workspace, three mcp servers, and a shared toolkit — plus the one rule stdio protocols never forgive - implementing the drain algorithm in rust
23 jan
turning a 2017 research paper into a streaming log-template extractor, and being honest about what i cut - i didn't leave go for rust. i split my stack.
16 jan
the 'which language' question is the wrong question. go for services, rust for tools — and here's the exact line.
2025 · 7 posts
the year things broke quietly. a vote handler that lost 79% of every rating change under load. a rate limiter that trusted a header anyone can set. an audit trail written for a table that would never be that small again. none of them threw an error, and that is the thread that ends up running through everything after it.
- i audited my side project like it was about to go viral (before it was)
29 jan
seed a fake gone-viral database, EXPLAIN ANALYZE the hot paths, and find the public stats page that was a denial-of-service you host yourself - your rate limiter trusts x-forwarded-for. mine did too, until it was measured.
22 jan
two measured bypasses of an anti-abuse limiter — a rotating forwarded header and a missing cookie — and the trusted-proxy fix - the elo race that silently ate 79% of every vote
15 jan
a textbook lost-update bug: a read-modify-write vote handler that lost 79% of every rating change under load - sqlc + pgx over an orm: type-safe sql that fails at compile time
24 jan
hand-written sql compiled to type-safe go, and why the orm in go.mod was dead code - vibe coding: the tiktok of programming
21 jan
the dangerous dopamine trap of large language models in coding - the solo founder's guide to enterprise-grade infrastructure on a budget
11 jan
how to build production-ready infrastructure when it's just you and your wallet - testcontainers 103
08 jan
part three, where i throw the whole suite away: a solo dev's case for shipping untested — which i retracted a year later, after a silent bug ate 79% of my data
2024 · 7 posts
the go monolith year. i was learning by building one service properly rather than five badly: ports and adapters without the ceremony, everything in a single binary with go:embed, and the boilerplate tax that comes due somewhere around the fourteenth entity. the testcontainers series starts here too, which is funny in hindsight given where 2025 went.
- owner-scoped rbac: enforcing 'you can only see your own'
23 jan
a two-tier global-vs-owned permission model in go, and the authorization inconsistency that hides when you scatter the check across layers - the boilerplate tax: fourteen entities, an 890-line router, and go
09 jan
an honest retrospective on structural duplication in a hexagonal go codebase — and when copy-paste actually beats codegen - shipping a single self-contained go binary
18 jan
embedded migrations and a self-writing config, so the service boots with zero external files - hexagonal architecture in go without the ceremony
14 jan
ports and adapters + ddd in idiomatic go, and exactly where the discipline pays off - testcontainers 102
22 jan
reusable container and migration helpers instead of part one's copy-paste setup, plus the validation, filter and concurrency cases the first pass skipped - testcontainers 101
15 jan
integration tests against a real postgres in docker rather than a mock or a sqlite pretending to be production — the setup, and the go repository layer under it - the meta post
13 jan
the post about how this blog came to exist