Go 1.23 Range Over Functions: What It's For and What It Isn't

Go 1.23 stabilised range over function iterators, a feature that had been in the rangefunc experiment since 1.22. It’s the most significant addition to the range statement since channels were added. The reaction has been mixed: people who needed it find it elegant; people who didn’t need it find it confusing. Both reactions are reasonable. Here’s what it actually does and where it belongs. ...

June 18, 2025 · 5 min · MW

RAG Systems in Production: What the Tutorials Don't Cover

RAG is architecturally simple: chunk documents, embed them, store in a vector DB, retrieve the top-k on query, pass retrieved context to an LLM, return answer. The demo takes an afternoon. The production system takes months, because “works on the demo documents” is nowhere near “answers correctly 95% of the time across the full document corpus.” This post is about the gap between those two states. ...

September 11, 2024 · 7 min · MW

LLM Integration Patterns for Backend Engineers

LLM integration is a new category of external API call with some specific failure modes that don’t exist in traditional services. The call is expensive (100ms–5s), non-deterministic, and can fail softly — returning a plausible-looking wrong answer rather than an error code. Getting it right requires the same rigor you’d apply to any critical external dependency, plus some LLM-specific patterns. ...

July 10, 2024 · 6 min · MW

Cache Design as a Reliability Practice, Not an Optimisation

At the large US tech company, I inherited a service that had a cache. The cache was fast — it served 98% of requests with <1ms latency. The 2% cache misses hit the database, which took 50–200ms. Then the cache cluster had a rolling restart during a traffic spike. For three minutes, the cache hit rate dropped to 30%. The 70% misses all hit the database simultaneously. The database became saturated, latency spiked to 10s, and the service effectively went down — not because the cache was unavailable, but because the system wasn’t designed for cache misses at that rate. This is a cache reliability failure, not a cache performance failure. ...

March 27, 2024 · 6 min · MW

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 net/http: Building Production HTTP Servers Without a Framework

Go’s net/http is frequently underrated. The ecosystem has frameworks — Chi, Gin, Echo, Fiber — and they’re fine choices, but the standard library gets you remarkably far without additional dependencies. After building several production APIs that stayed on raw net/http, here’s the honest assessment of what you can and can’t do without a framework, and the patterns that make it work. ...

July 5, 2023 · 6 min · MW

ClickHouse for Application Analytics: Fast Aggregations Without Spark

The requirement: an internal analytics dashboard showing trading activity metrics — volume, trade count, latency distributions, error rates — sliced by instrument, venue, time window, and a dozen other dimensions. Data volume: about 4 billion events per day, 90-day retention. Query pattern: ad-hoc OLAP — arbitrary group-bys, time ranges, filters. We evaluated TimescaleDB (Postgres extension), Apache Druid, ClickHouse, and “just use BigQuery.” We chose ClickHouse. After a year in production, I’d make the same choice. ...

May 17, 2023 · 5 min · MW

Database Access Patterns in Go: sqlx, pgx, and When to Use an ORM

The first question on every new Go service with a database: standard library database/sql? sqlx? pgx directly? An ORM like GORM? sqlc for code generation? The honest answer is that the right choice depends on the access pattern, the team’s SQL proficiency, and how much you value type safety at the cost of verbosity. Here’s what each option looks like in practice. ...

April 5, 2023 · 6 min · MW

Feature Flags at Scale: Beyond the On/Off Switch

The first feature flag I implemented was a boolean in a config file. Toggle it to true, deploy, feature is on. Toggle to false, deploy, feature is off. Simple. The fifteenth feature flag was a percentage rollout with user cohort targeting, metric-based automatic rollback, and a kill-switch that worked without a deployment. The gap between those two implementations is what this post is about. ...

February 28, 2023 · 6 min · MW

Writing Idiomatic Go

Go has a strong house style that experienced practitioners converge on. Some of it is enforced by gofmt and golint. The rest is transmitted through code reviews, the standard library, and writing enough Go to feel the natural grain of the language. After several years of Go, here are the patterns that mark idiomatic code and why they work. ...

January 11, 2023 · 6 min · MW
Available for consulting Distributed systems · Low-latency architecture · Go · LLM integration & RAG · Technical leadership
hello@turboawesome.win