Recent writings

If you won't carry the pager, maybe don't push to mainline · article

Drive-by AI changes break the shared model a team builds around its code, and the ICs end up cleaning up the mess. Why pushing to mainline should come with the pager.

Testing Go CLIs with testscript · article

How cmd/go's script tests led me to testscript, and how to use it for CLI tests that exercise argv, stdout, stderr, exit codes, and scratch files.

A tour of txtar · article

txtar is a tiny plain-text archive format Russ Cox introduced in 2018 for multi-file test fixtures. The Go Playground, cmd/go's script tests, gopls's marker tests, and rsc.io/rf all reach for it.

Type-safe slogging · article

The default slog API is loose enough that a careless line ships broken JSON to production. Pin it down with Attr constructors, LogAttrs, a context-borne logger, and sloglint.

Hoisting wire plumbing out of your Go handlers · article

Four of the five steps in every unary RPC handler are wire plumbing. Pin the service function signature and they fit in one generic adapter per transport.

Go quirks: function closures capturing mutable references · article

A Go closure holds a live reference to whatever it captures, not a snapshot. Real examples of where this trips people up, and how to keep it boring.

Accepted proposal: UUID in the Go standard library · shard

Notes on Go's newly accepted uuid proposal and the tradeoffs behind the API.

Peeking into Go struct tags · article

A quick tour of Go struct tags: how different libraries use them, how you read them at runtime with reflection, and how other tools read them at build time instead.

Error translation in Go services · article

Translating errors at layer boundaries so storage details don't leak into the handler or, worse, into client responses.

Dynamo: Amazon's highly available key-value store · paper

Key takeaways from Amazon's 2007 Dynamo paper.

Stacked log lines considered harmful · shard

Why logging at every layer of a service produces noise, and how to log only at the handler level while propagating context from below.

What's the ideal dispatch mechanism? · shard

Switch, map of functions, and interface registry for dispatching in Go.

Background jobs and inherited file descriptors · shard

Why & backgrounds execution but doesn't stop output from flooding your terminal.

Testing unary gRPC services in Go · article

How to test unary gRPC services in Go - handler logic, interceptors, deadlines, metadata propagation, and rich error details - all in-memory with bufconn.

Repositories, transactions, and unit of work in Go · article

Decoupling business logic from storage in Go, adding transaction support without leaking SQL details, and coordinating atomic writes across multiple repositories using a unit of work.