Logo
Logo
7 results for
  • After I shipped the event-sourced account system, the first question from the product team was: “Can we have a page that shows all accounts that have been dormant for more than 90 days?” In a traditional system, this is a query: SELECT * FROM accounts WHERE last_activity < NOW() - INTERVAL '90 days'. In event sourcing, there’s no last_activity column — there’s an event stream. My first instinct was to query the event store directly, find the latest event per stream, and filter. It worked. Then they asked for the top 100 accounts by balance. Then active accounts by geography. Then a real-time dashboard with all of the above simultaneously. Querying the event store for each of these is either very slow or very complex. The answer is projections — pre-computed read models built from your event streams.

    fundamentals architecture event sourcing Created Fri, 13 Sep 2024 00:00:00 +0000
  • CLI tools spend most of their life doing file I/O. Reading config files, processing log dumps, writing output, transforming data from stdin to stdout — it all comes down to bytes moving through your program. The difference between a CLI tool that handles 100MB files gracefully and one that runs out of memory on large inputs is almost always whether you read everything into memory or stream it.

    Go’s standard library gives you everything you need to stream data efficiently. The key is knowing which functions to reach for and which ones to avoid when the input is large or unknown in size.

    Go tutorial golang CLI Created Thu, 12 Sep 2024 00:00:00 +0000
  • Every tool starts as mytool --flag input.txt. Then someone asks for a second mode. Then a third. Before you know it, you have mytool --mode=convert --input foo --output bar and mytool --mode=validate --strict --input foo and users are scrolling through --help trying to find the three flags that matter for their use case. The answer is subcommands. git commit, docker build, cargo test — separate commands with separate flags, unified under one binary.

    Rust tutorial rust cli Created Wed, 11 Sep 2024 13:50:00 +0000
  • Every time I’ve seen a team choose their inter-service communication protocol by default — “we’ll use REST for everything” or “we’re going gRPC-native” — they’ve ended up with a transport mechanism that fights against some of their use cases. The choice between HTTP, gRPC, and event-driven messaging is a question about coupling: how tightly do these services need to be synchronized? The answer to that question selects your transport, not the other way around.

    Go tutorial golang microservices Created Tue, 10 Sep 2024 00:00:00 +0000
  • I had a CLI tool that converted video files. Big ones — 10, 20 gigabytes each. The conversion created a temp file, wrote the converted output there, then renamed it to the final destination. Hit Ctrl+C at the wrong moment and you’d get a half-written 15GB temp file sitting on disk. Users ran out of disk space without knowing why. All because I never handled signals properly.

    What Happens When You Press Ctrl+C

    When you press Ctrl+C in a terminal, the kernel sends SIGINT (signal interrupt) to the foreground process group. By default, this kills your program immediately. No destructors run. No Drop implementations execute. Temporary files stay on disk. Database connections aren’t closed. Partial writes aren’t rolled back.

    Rust tutorial rust cli Created Mon, 09 Sep 2024 09:17:00 +0000
  • I watched a Postgres instance run out of disk space on a 500 GB SSD. The database had 50 GB of actual data. The other 450 GB was table bloat — dead row versions from MVCC that vacuum had failed to clean up. A batch job had been running long-running transactions for weeks, holding a transaction horizon that prevented vacuum from reclaiming anything. By the time we noticed, the disk was nearly full and autovacuum was struggling to catch up. Understanding why this happens — and how to prevent it — is one of the most important operational skills for running Postgres in production.

    fundamentals databases Created Mon, 09 Sep 2024 00:00:00 +0000
  • I inherited a Rust project with 800 tests. Running them took 45 minutes. I dug in and found: 600 unit tests that mocked every dependency (most tested nothing meaningful), 180 integration tests that duplicated what the unit tests already covered, and 20 end-to-end tests that were flaky because they hit a staging server. The project had more tests than any codebase I’d seen — and also more bugs. The volume was high, but the strategy was garbage.

    Rust tutorial rust testing Created Sun, 08 Sep 2024 11:10:00 +0000
  • The schema is the most important artifact in any GraphQL API. It is simultaneously the contract between your client and server, the documentation for every engineer who works with the API, and the boundary that forces you to think clearly about your domain before writing any implementation code. A well-designed schema makes everything easier. A poorly designed schema compounds every mistake downstream.

    I’ve seen both. The experience of inheriting a badly designed GraphQL schema — full of inconsistent naming, misused types, nullable fields everywhere because someone wasn’t sure — is one of the more persistent forms of technical debt I’ve encountered. Unlike a poorly written function, a bad schema is public-facing. You can’t just refactor it; you have to version and deprecate carefully.

    fundamentals GraphQL API Created Sun, 08 Sep 2024 00:00:00 +0000
  • Every powerful tool has a failure mode that looks like success. With generics, the failure mode is this: you write something that compiles, works correctly, and is impressively abstract — but your teammates can’t read it, can’t debug it, and quietly work around it. I’ve written code like that. It felt clever in the moment. It was a problem in practice.

    This lesson is about the patterns that sound good and turn out badly. I’m calling them out explicitly because they’re seductive — especially if you’ve spent time in Haskell or Scala and you know what generic abstractions can look like.

    Go tutorial golang generics Created Sun, 08 Sep 2024 00:00:00 +0000
  • I used to think terminal output was either plain text or ANSI escape code soup. Then I looked at how tools like cargo, ripgrep, and bat handle their output — color used purposefully to draw the eye, progress bars that give you actual information, spinners that tell you something is happening. Good terminal UX isn’t about making things pretty. It’s about making information scannable.

    Raw ANSI Escape Codes

    Before using any crate, you should understand what’s actually happening. Terminal colors are just special byte sequences embedded in the output stream:

    Rust tutorial rust cli Created Sat, 07 Sep 2024 16:33:00 +0000