Logo
Logo
4 results for
  • A few months into my first production Go service, I had a bug that cost me two hours. A function returned an error, I checked if err != nil and it passed — but then further down the stack the program panicked trying to call .Error() on a nil pointer. The function had returned a nil *MyError, not a nil error. These are not the same thing, and until you internalize why, you will hit this bug.

    Go tutorial golang internals Created Thu, 18 Jul 2024 00:00:00 +0000
  • The first JSON API I replaced with gRPC was passing []Order objects around — each order had about 40 fields, most of which the caller never used. The JSON payload for a list of 100 orders was around 180KB. After the migration it was 22KB, and the serialization time in benchmarks dropped by 8x. But more than the performance numbers, what I noticed was the schema. Proto files are contracts. When a field changes, you know it. With JSON, you find out when things break in production.

    fundamentals networking Created Wed, 17 Jul 2024 00:00:00 +0000
  • There’s a dirty secret in Rust error handling: half the time, you don’t actually need typed errors. You need errors that are easy to create, easy to chain, and easy to print. That’s anyhow. Same author as thiserror (David Tolnay), completely different use case. Where thiserror is for defining precise error types, anyhow is for using errors without ceremony.

    The Problem anyhow Solves

    Without anyhow, when you have a function that can fail in multiple unrelated ways, you either:

    Rust tutorial rust error-handling Created Tue, 16 Jul 2024 16:20:00 +0000
  • There’s a class of performance bugs in Go that doesn’t show up in code review, doesn’t trigger the race detector, and doesn’t cause test failures. It just makes your service slowly worse under load. The source is almost always the same: heap allocations happening in places you didn’t intend, turning what should be fast stack operations into GC-visible objects that pile up until the collector has to stop and clean them up. Building an intuition for when Go allocates on the heap versus the stack was one of the single highest-leverage things I did to improve the services I work on.

    Go tutorial golang performance Created Tue, 16 Jul 2024 00:00:00 +0000
  • There is a convention I spent a long time following without questioning it: put the interface in the same package as the type that implements it. If I had a payment package with a Stripe struct, I would also define PaymentProcessor right there. Callers would import payment.PaymentProcessor. It felt natural — the interface lives next to the thing it describes.

    Go’s designers had a different idea in mind, and it took me several refactoring sessions on a real codebase before I understood why it matters: interfaces should be defined by the package that uses them, not the package that implements them. The Go standard library does this consistently and for good reason.

    Go tutorial golang interfaces Created Mon, 15 Jul 2024 00:00:00 +0000
  • Google Docs is the problem I recommend to every engineer who thinks they understand distributed systems. The surface looks trivial: multiple users editing a document simultaneously. The depth is staggering. When two users type at the same position in a document at the same millisecond, what does each user see? How do you converge on a consistent state without a central lock? How do you preserve the intention behind each edit, not just the characters?

    fundamentals system design interviews Created Mon, 15 Jul 2024 00:00:00 +0000
  • After writing my third custom error type by hand — with the Display impl, the Error impl, the From impls — I thought, “there has to be a better way.” There was. It’s called thiserror, and it’s probably the most widely-used error handling crate in the Rust ecosystem. David Tolnay wrote it, which means it’s well-designed, well-maintained, and does exactly one thing with zero bloat.

    What thiserror Does

    thiserror is a derive macro that generates Display, Error, and From implementations for your error types. It produces the exact same code you’d write by hand — no runtime cost, no extra dependencies at runtime (it’s a proc-macro, so it’s only a compile-time dependency).

    Rust tutorial rust error-handling Created Sun, 14 Jul 2024 10:00:00 +0000
  • The first time I deployed a service to Kubernetes and watched it restart, I noticed that requests in flight were sometimes failing with connection resets. The pod was receiving 502 responses for a few seconds before it disappeared. I had heard of “graceful shutdown” but hadn’t implemented it. Kubernetes sends SIGTERM before killing a process, giving it time to finish in-flight requests — but my service was either ignoring the signal or exiting immediately, cutting off connections mid-request. Learning how signals work at the OS level, and then implementing correct signal handling in Go, fixed the issue permanently.

    fundamentals linux operating systems Created Sun, 14 Jul 2024 00:00:00 +0000
  • We load-tested our new checkout service before launch. 1,000 virtual users, 10 minutes, all hitting /v1/checkout sequentially. It passed with excellent numbers. Launch day: real traffic hit the service, and it fell over at 200 concurrent users. The problem was our test. Real users don’t all call the same endpoint in sequence. They browse, add to cart, apply discount codes, fill in addresses, and then checkout — a session that touches 8 different endpoints over 4 minutes. Our test didn’t model this. Our test was measuring the wrong thing.

    fundamentals engineering practices Created Sat, 13 Jul 2024 00:00:00 +0000
  • GATs (Generic Associated Types) took seven years from proposal to stabilization. That’s not because Rust’s team is slow — it’s because GATs are genuinely hard to get right, and they unlock patterns that were previously impossible without unsafe code or painful workarounds. When they finally landed in Rust 1.65, I immediately rewrote a chunk of a database abstraction layer that had been haunting me for months.

    The one-liner: GATs let associated types have their own generic parameters, including lifetimes.

    Rust tutorial rust traits generics Created Fri, 12 Jul 2024 18:00:00 +0000