Posts
Things I’ve written that are long enough to deserve an introduction. Mostly backend engineering, occasional detour into photography and espresso machines.
-
http.Client tuning for a flaky upstream
A checklist of the settings I reach for when a Go service needs to talk to an upstream that's... not great
-
The branch predictor ate my microbenchmark
I was sure one version of a hot loop was faster; I was wrong; it was the CPU making me look smart
-
tokio::sync vs std::sync in a real service
When to reach for a blocking std::sync::Mutex in async code and when you must use tokio's version
-
Build tags are the quiet power tool of Go
Conditional compilation in Go via build tags is simpler than most preprocessor systems and I use it more than I expected
-
Error wrapping conventions I settled on
After years of churn, the error handling style that has held up across three services and five engineers
-
Generics in Go, eighteen months later
What I use generics for, what I don't, and the subtle ways they interact with method sets and interfaces
-
The day I learned Mach-O segments matter
Shipping a Go binary that loaded fine on Linux but segfaulted on macOS led me down a rabbit hole of executable file formats
-
Atomic ordering made sense after I drew it on paper
Acquire, release, relaxed, sequential consistency — I finally have an intuition for when to use which
-
go.sum conflicts during merges are always my fault
A short operational guide to resolving go.mod and go.sum conflicts without making the problem worse
-
Pin, Unpin, and why async Rust made me read a paper
Self-referential futures, what they imply for memory layout, and why Pin is not as scary as the type signature suggests
-
The GC knob that actually helped
GOMEMLIMIT is the Go runtime environment variable I wish I'd known about a year earlier
-
httptest.Server is better than you think
Most Go HTTP tests I see are mocked when they should be using httptest.Server, and it shows
-
Trait objects vs generics: when I finally picked a side
After waffling for months, I have a rule for when to use dyn Trait and when to use impl Trait, and it holds up
-
Benchmarking gotchas I learned the hard way
A collection of ways I made Go benchmarks lie to me, including the compiler optimizations I didn't know existed
-
Tokio's block_in_place is a footgun
It solves one problem cleanly and creates two others that don't show up until you're at scale