Panic recovery middleware that fails closed and logs context

Even well-tested services panic occasionally: a nil pointer from an unexpected edge case, a slice bounds bug, or a library doing something surprising. If you don’t recover, one request can crash the entire process and turn a small bug into an outage.

Retry Postgres serialization failures with bounded attempts

For workloads that run at SERIALIZABLE isolation (or that hit serialization conflicts under load), retries are part of the contract. The important part is to retry only the safe errors (typically SQLSTATE 40001) and to keep the loop bounded so you don

errors.Join for cleanup (surface multiple close failures)

Cleanup paths are easy to under-test, and it’s common to ignore close errors because you only have one return value. With Go 1.20+, errors.Join gives you a clean way to accumulate multiple cleanup errors and return them as a single error value. This i

Capture status code and bytes written via ResponseWriter wrapper

When you need accurate request logs or metrics, you can’t rely on “what you intended to write” — you need what actually got written. Wrapping http.ResponseWriter to capture WriteHeader and count bytes is a simple way to record status codes and respons

WriteJSON helper with consistent headers and status

I like explicit response helpers because they prevent subtle inconsistencies: missing Content-Type, forgetting Cache-Control, or writing headers after the body has started. A WriteJSON function centralizes the “happy path” and makes error handling con

Strict JSON decode helper (size limit + unknown fields)

Most handler bugs I debug are really input bugs: oversized bodies, unexpected fields, or clients sending arrays when the API expects an object. A dedicated decode helper makes behavior consistent. This pattern wraps the request body with http.MaxBytes

Track in-flight requests with atomic counters

In-flight request count is a simple but powerful saturation signal. I keep an atomic.Int64 gauge that increments at the start of a request and decrements in a defer, which makes it robust even on early returns. This gauge can be exported via expvar, P

Content sniffing for uploads (don't trust the header)

Clients can lie about Content-Type, so for uploads I prefer sniffing the first bytes with http.DetectContentType. The safe flow is: open the multipart file, read a small prefix, detect type, then rewind (or re-open) before writing to disk or object st

Idempotent event consumer with processed-events table

At-least-once delivery is the default for most queues and streams, so consumers must be idempotent. My go-to pattern is a processed_events table keyed by event_id with a unique constraint. When a message arrives, the consumer tries to insert event_id;

expvar counters for quick-and-dirty production introspection

Sometimes you want a quick diagnostic without wiring a full metrics stack. expvar exposes variables at /debug/vars in a standard JSON format. I use it for a handful of counters like “requeststotal” and “jobsfailed” when I’m bootstrapping a service or

Set a soft memory limit with debug.SetMemoryLimit

In containerized environments, the Go runtime can benefit from knowing the memory budget. With Go 1.19+, debug.SetMemoryLimit lets you set a soft limit so the GC reacts more aggressively before the process gets killed by the OOM killer. I treat this a

sync.Pool for bytes.Buffer to reduce allocations in hot paths

For high-throughput endpoints that serialize JSON or build strings repeatedly, allocations can become a real cost. sync.Pool is a pragmatic tool for reusing temporary buffers without manual free lists. The key is to treat pooled objects as ephemeral: