Logo
Logo
249 results for
  • I spent two years writing Go services that logged like this:

    log.Printf("processing order %s for user %d, amount %.2f", orderID, userID, amount)
    

    It worked fine — until the day I needed to find every failed payment over $500 from a specific user across three weeks of logs in a production incident at 2 AM. I was grepping through gigabytes of text, trying to parse freeform strings with jq, getting nowhere. The logs existed. The information was technically there. But I couldn’t query it in any meaningful way.

    Go tutorial golang observability Created Tue, 25 Jun 2024 00:00:00 +0000
  • The on-call rotation I inherited had 47 active alerts. On a bad week, the on-call engineer got paged 30 times. Most pages were “something might be wrong” noise — high CPU on one instance, a spike in error rate that self-resolved in 30 seconds, disk space at 70% on a server with months of capacity remaining. Engineers stopped taking the pages seriously. Then the one real incident got buried in the noise, and we had a 4-hour outage because no one treated the first alert seriously. Alert fatigue is not a monitoring problem. It’s an architecture-of-trust problem.

    fundamentals engineering practices Created Mon, 24 Jun 2024 00:00:00 +0000
  • Every Rust programmer hits this wall eventually. You have a Vec and you want to put different types in it — all implementing the same trait, but different concrete types. You try Vec<impl Trait> and the compiler says no. You try Vec<T> with generics and realize T can only be one type at a time. That’s when you discover dyn Trait, and the first real tradeoff in Rust’s type system: static dispatch vs dynamic dispatch.

    Rust tutorial rust traits generics Created Sun, 23 Jun 2024 19:15:00 +0000
  • I shipped a bug once that allowed a user to spend the same gift card balance twice. Two requests arrived nearly simultaneously, both read the same balance, both decided the balance was sufficient, both deducted it, and both succeeded. The database did exactly what I asked. The problem was what I asked for: I assumed reads were consistent across statements within a transaction, but I was running at the default isolation level. Understanding the four isolation levels — and what each one actually protects you from — is not academic. It is the difference between shipping correct financial code and shipping race conditions.

    fundamentals databases Created Sun, 23 Jun 2024 00:00:00 +0000
  • Every Go project that grows into something useful eventually needs a command-line interface. Maybe it starts as a quick main.go with os.Args[1] checks and a switch statement. That works until you need subcommands, flags, help text, shell completion, and version information — and suddenly you are maintaining a hand-rolled argument parser that nobody wants to touch. Cobra is the standard library-grade solution to this problem, and learning to structure a Cobra application properly saves you from rewriting it twice.

    Go tutorial golang CLI Created Sat, 22 Jun 2024 00:00:00 +0000
  • I had a trait called Serialize (homebrew, pre-serde days) that needed to format things as strings. I kept calling .to_string() inside default methods and wondering why the compiler complained. The type implementing my trait didn’t necessarily implement Display. The fix was obvious in hindsight — make Display a supertrait of Serialize. If you want to serialize, you must be displayable. Period.

    Supertraits let you build trait hierarchies where implementing one trait requires implementing another.

    Rust tutorial rust traits generics Created Fri, 21 Jun 2024 08:50:00 +0000
  • I maintained an e-commerce admin dashboard that had a query so complex it took 12 seconds to run. It joined seven tables across the orders, inventory, and customers domains to build a summary view of “all orders pending fulfillment, with customer tier, item details, and warehouse stock levels.” Every time the admin loaded the page, twelve seconds. We tried indexes, caching, materialized views — all helped at the margins. The fundamental problem was that we were asking our write-optimized relational model to answer a read-optimized reporting question. Separating the read model was the only real fix.

    fundamentals architecture Created Fri, 21 Jun 2024 00:00:00 +0000
  • I spent the first two years of writing Go completely unaware that the compiler was making decisions about my code that I never asked for — and that those decisions were quietly shaping the performance profile of everything I shipped. Escape analysis is the mechanism behind all of it. Once I understood it, I started reading code differently. Not just “does this work?” but “where does this data live, and did I give the compiler a chance to put it somewhere fast?”

    Go tutorial golang performance Created Thu, 20 Jun 2024 00:00:00 +0000
  • Here’s a question that confused me for months: why does Iterator use an associated type (type Item) instead of a generic parameter (Iterator<T>)? They look like they do the same thing. They kinda do. But the choice between them changes your entire API’s ergonomics, and picking wrong leads to annoying code downstream.

    The short answer: associated types mean “one implementation per type,” generic parameters mean “many implementations per type.” But the implications are deeper than that.

    Rust tutorial rust traits generics Created Wed, 19 Jun 2024 16:05:00 +0000
  • Synchronous calls are elegant until they’re not. Service A calls Service B. B is slow. A waits. A’s request pool fills up. A becomes slow. The caller of A waits. The whole request chain stalls. Add a few more services in the chain and you have a distributed deadlock in slow motion. Message queues exist to break this dependency — to let a producer say “here’s some work” and move on, without caring whether the consumer is fast, slow, or temporarily down.

    fundamentals system design Created Wed, 19 Jun 2024 00:00:00 +0000