Structured Logging in Go: slog, zerolog, and What Actually Matters

Unstructured logging is a debugging tool. Structured logging is an observability tool. The difference: unstructured logs tell a human what happened; structured logs tell a machine what happened, and the machine can then tell a human efficiently. Unstructured: 2022-11-23 10:58:34 ERROR failed to process order ORD-12345 for user usr_abc: connection refused Structured: {"time":"2022-11-23T10:58:34Z","level":"ERROR","msg":"failed to process order", "order_id":"ORD-12345","user_id":"usr_abc","error":"connection refused", "service":"order-service","version":"1.2.3"} The structured log can be indexed, filtered, aggregated, and alerted on. order_id:ORD-12345 returns all logs for that order across all services. The unstructured log requires grep and hope. ...

November 23, 2022 · 5 min · MW

Memory Layout in Go: Structs, Alignment, and Cache Performance

This is the JVM false-sharing problem in a different language. The rules differ slightly, the tooling differs, but the underlying hardware constraint — cache lines are 64 bytes and sharing one across goroutines is expensive — is identical. ...

August 17, 2022 · 5 min · MW

OpenTelemetry in Go: Distributed Tracing That Doesn't Get in the Way

Before OpenTelemetry, distributed tracing was a vendor-specific integration. You chose Jaeger or Zipkin or Datadog, added their SDK, and traced against their API. Switching vendors meant rewriting instrumentation. Adding a library that used a different tracing SDK meant two tracing systems running in parallel. OpenTelemetry solved this with a vendor-neutral API and a pluggable exporter model. The API stays the same; you swap exporters. Most major observability vendors now accept OTel format natively. Here’s what a solid Go integration looks like. ...

May 31, 2022 · 5 min · MW

Embedding in Go: Composition Over Inheritance Done Right

Go’s lack of inheritance is deliberate. The Go designers observed that inheritance hierarchies tend to create tight coupling and fragile base classes — problems that composition avoids. Embedding is Go’s tool for composition: you can embed one type in another and promote its methods, without inheritance’s downsides. It’s more powerful and more subtle than it appears. ...

January 5, 2022 · 5 min · MW

Building Reliable Pipelines with Go: Retry, Circuit Breaker, and Backoff

A service that calls a database, calls another service, or writes to a message queue will eventually encounter a failure. The question is not whether — it’s whether your service handles failures gracefully or cascades them into a larger outage. These patterns are well-documented in the resilience literature. What this post focuses on is the specific Go implementation and the traps that make naive implementations incorrect. ...

November 17, 2021 · 6 min · MW

Go 1.18 Generics: Real Use Cases Worth the Complexity

Go 1.18 was still months away when the design was finalised, but the proposal was public and we were already prototyping. After building several services at the European fintech firm with the experimental toolchain, the pattern of when generics help versus when they don’t was becoming clear. The answer is not “always use generics” or “avoid them.” It’s more specific than that. ...

April 7, 2021 · 5 min · MW

gRPC in Production: Lessons After Two Years

We moved our internal service communication from REST+JSON to gRPC when the data pipeline scaled past a point where JSON parsing overhead was measurable in profiles. Two years later, the performance win was real and smaller than expected; the developer experience wins were larger; and the operational complexity was a genuine tax that we underpriced initially. ...

January 13, 2021 · 4 min · MW

Generics Are Coming to Go: What the Proposal Actually Solves

Go had resisted generics for years. The arguments against were practical: generics complicate the language, they interact badly with Go’s interface system, and most cases where you want generics can be handled with interface composition or code generation. The arguments weren’t wrong. But the proposal that eventually shipped in Go 1.18 (2022) addressed a real gap — a gap that was producing either duplicated code or interface{} with runtime type assertions everywhere. Here’s what the proposal was solving. ...

October 5, 2020 · 5 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
Available for consulting Distributed systems · Low-latency architecture · Go · LLM integration & RAG · Technical leadership
hello@turboawesome.win