Go's Race Detector in CI: Catching Data Races Before They Catch You

A data race is a program that reads and writes shared memory concurrently without synchronisation. The behaviour is undefined: you might get the old value, the new value, a torn read (part old, part new), or a crash. Reproducing the bug is usually impossible because it depends on precise CPU scheduling. Go’s race detector is a compile-time instrumentation tool that detects these at runtime. It’s one of the most useful debugging tools in the Go ecosystem and one of the most underused. ...

October 4, 2023 · 6 min · MW

Go's Scheduler: GOMAXPROCS, Work Stealing, and Why It Matters

Go’s goroutine scheduler sits between your code and the OS. Understanding it is useful not because you’ll tune it (you rarely should) but because its behaviour explains a class of performance surprises and concurrency patterns that look odd until you see why they exist. ...

August 12, 2020 · 5 min · MW

Building a High-Throughput Event Pipeline in Go Without Losing Your Mind

The fintech startup processed market events at sustained rates of 50,000–200,000 per second through a normalisation and enrichment pipeline. Go channels and goroutines are the natural tool. The naive implementation falls apart at scale. Here’s what works. ...

July 1, 2020 · 6 min · MW

Context Propagation in Go: Deadlines, Cancellation, and Tracing

context.Context appears in the signature of almost every non-trivial Go function. It’s the idiomatic way to carry deadlines, cancellation signals, and request-scoped values across API boundaries and goroutines. After years of reading Go codebases, the misuse patterns are as common as the correct uses. ...

February 19, 2020 · 5 min · MW

Channels vs Mutexes: When to Use Which in Go

Go has a famous concurrency proverb: “Do not communicate by sharing memory; instead, share memory by communicating.” This is good advice. It’s also misapplied regularly. Channels are not universally better than mutexes — they’re a different tool for a different set of problems. After years of Go in production, here’s when I reach for each. ...

August 7, 2019 · 5 min · MW

Goroutines Are Not Threads: The Mental Model Shift

The first thing every Java developer learns about goroutines is that they’re cheap. Start a million of them, no problem. The mental model that follows from this — “goroutines are threads but lighter” — is close enough to be useful and wrong enough to cause confusion. Here’s the refined model. ...

April 22, 2019 · 6 min · MW

Go for the Seasoned Java Developer: What Feels Familiar, What Doesn't

I had written maybe 500 lines of Go before the new role. Within two months it was my primary language. This is the honest transition account — not a “Go vs Java” opinion piece, but what the practical experience of switching felt like. ...

February 20, 2019 · 4 min · MW

Project Loom Preview: Virtual Threads and What They Mean for Server Code

Java’s threading model has a fundamental scalability problem: OS threads are expensive. Creating thousands of them consumes gigabytes of stack memory and causes significant scheduling overhead. This is why reactive programming (Netty, Project Reactor, RxJava) became popular — it avoids the thread-per-request model by using event loops and async callbacks. Project Loom, announced in 2017 with early previews arriving in 2018, proposed a different solution: make threads cheap. Virtual threads — JVM-managed threads that are not 1:1 with OS threads — could make the thread-per-request model scalable again. ...

May 24, 2018 · 5 min · MW

Persistent Data Structures Are Not Just for Functional Purists

When I joined the bank’s risk team, Clojure was already in production for risk calculation. The code I inherited used Clojure’s persistent maps and vectors everywhere — not as a philosophical statement but because the team had found them practically useful in a specific way. The specific way: concurrent reads and occasional writes to a shared state snapshot, with no locks. ...

August 16, 2017 · 5 min · MW

Threading Models in Java: Which One Does Your System Actually Need?

The move from a small trading firm to a large financial institution meant working with codebases an order of magnitude larger, maintained by dozens of engineers across multiple teams. It also meant encountering the full spectrum of Java threading models in production — some appropriate, some inherited from a different era, and some that were actively causing problems. This is a survey of what those models look like, what they’re good at, and how you tell which one a system needs. ...

November 9, 2016 · 5 min · MW
Available for consulting Distributed systems · Low-latency architecture · Go · LLM integration & RAG · Technical leadership
hello@turboawesome.win