Notes from the field.
Long-form writing on Go, web architecture, open source maintenance and what it's like to run a small software studio in 2026.
What AI coding tools changed in our workflow
We've used AI coding assistants seriously for a year. Here's what genuinely changed, what didn't, and the failure mode nobody talks about.
Read the post →OpenTelemetry is the observability standard. How to instrument a Go backend with traces, metrics, and logs — without wrapping the whole codebase.
SQLite stopped being a prototype DB in 2025. Between Litestream, Turso, and WAL mode, there's a real production case. Here's when to reach for it.
Kafka is the default choice for event streaming. NATS is the thing you pick when you've run Kafka once. Here's when each is actually right.
Platform engineering is the hot infra job title. Most writing about it assumes 50 engineers. Here's what it actually looks like at five.
Adding AI to a backend isn't about a new framework. It's structured prompts, tool use, streaming responses, and failure modes you haven't seen.
A complete walkthrough: user registration, password hashing, JWT signing, protected routes, and refresh tokens — no auth library required.
Most teams pick a software development partner the wrong way. Here's the short list of signals that actually predict a good engagement.
Sessions and tokens are both valid. They have different trade-offs and different failure modes. Here's how to pick the right one for your Go backend.
Why every serious CLI tool needs a retry budget, a structured error surface, and a story for SIGTERM — and how we codified that in resilient-cli.
The build-vs-buy decision isn't really about cost. It's about which parts of your business you're willing to outsource to someone else's roadmap.
Clean architecture has good ideas and some dead weight. Here's how we adapt it for Go backends — keeping the domain isolation, dropping the ceremony.
Most MVPs ship late because they were scoped on a whiteboard, not against a calendar. Here's the scoping pass we run before we quote a number.
ORMs hide Postgres from you. sqlc and pgx expose it — with type safety, generated queries, and connection pooling that actually works under load.
Go doesn't need a DI container. It needs constructor functions and a main.go that wires everything together. Here's the pattern we use on every project.
gomigrate is our open-source migration tool for Go and Postgres. Plain SQL, embedded files, atomic transactions, CI-friendly CLI — here's everything it does.
Layered architectures feel tidy on paper. In a four-person team shipping weekly, they mostly generate meetings. Here's what we do instead.
Most migration guides change a schema. This one changes it while the app is running, using the expand/contract pattern with gomigrate.
RLS is a genuinely good feature stapled on top of genuinely scary defaults. A field guide from three production rollouts.
The honest answer to "how much does an app cost?" is a list of decisions you haven't made yet. Here's the list.
Three solid options, different trade-offs. Here's the comparison we run in our head when starting a new Go backend — and the one we usually land on.
Inconsistent errors are a support ticket waiting to happen. Here's the validation and error-handling shape we standardise across every Go API we ship.
Free discovery calls feel generous. They mostly select for clients who don't value the work. Here's the framing we use instead.
Go middleware is just a function that wraps a handler. That simplicity is a feature — here are the three patterns every Go backend needs, implemented cleanly.
The first platform you ship on shapes the next year of your product. Pick it for the right reasons, not because of a stock photo of a phone.
GitHub Actions, a single shell script, and a Caddy server. What our deploys actually look like after the shiny wears off.
Outsourcing isn't a strategy. It's a tool with a narrow set of correct uses. Here are the four we've seen work and the three that always burn.
Every API ages. The question is whether it ages like wine or like milk. Six rules we apply on every public surface we ship.
Early-stage SaaS doesn't need microservices, Kubernetes, or a service mesh. It needs a boring monolith and a database you understand.
Technical screens filter for craft. But the thing that actually separates senior engineers is taste — and you can, carefully, interview for it.
Hiring an in-house team is the right answer eventually. It's almost never the right answer first. Here's the cost model we walk clients through.
Not all technical debt is bad. Some of it is the only reason you shipped at all. A working taxonomy after a decade of cleanup projects.