Retries are one of the easiest resilience patterns to add and one of the easiest to get wrong.
The idea is sound. Transient failures happen. Networks drop packets. Load balancers close idle connections. A database primary moves. A single failed call...
A cache is a promise with an expiration date.
That sounds obvious until a production system starts depending on cached state as if it were truth. Then the cache is no longer an optimization. It is a second source of truth with worse durability, weak...
I like caches that are easy to delete.
That may sound strange, because the whole point of a cache is that it improves something important: latency, cost, load, or availability. But the safest caches are the ones the system can survive without. They ...
If you have set up a remote build cache and watched the hit rate sit stubbornly low, nondeterministic outputs are one important suspect — but not the only one. Source churn, changing flags, platform differences, toolchain changes, eviction, and incom...
Most engineers think of the build as something that happens on their laptop. You type a command, the fans spin up, and a few minutes later you have a binary. That model is so ingrained that we rarely question it — until the codebase gets big enough t...
Go slices are simple on the surface. Under the hood, the interaction between length, capacity, and append has a specific failure mode I've been bitten by more than once — and seen in enough code reviews to write about. The bug is invisible at compile...
Go ships with a profiler built in. No third-party tools, no agents to install, no instrumentation to add upfront. If your service imports net/http/pprof, you can profile it live in production right now — CPU usage, memory allocations, goroutine count...
Every Go service that does I/O — database calls, HTTP requests, queue polling, file reads — should be passing a context.Context through every layer. In practice, a large number of codebases treat context.Context as optional plumbing that gets added l...
Go makes concurrency feel easy. Goroutines are cheap, channels are built into the language, and the standard library gives you everything you need to spin up a worker pool in under 30 lines. That ease is genuinely valuable — but it also means bugs sn...
Go Interfaces: Why Less Is Almost Always More
If you’re coming to Go from Java or C++, interfaces look familiar at first glance. You define a set of methods, types implement them, you write code against the interface. Same idea, right?
Not quite. ...