Blog

Why we build critical backends in Go

Not because of the benchmarks. Because of what a team can still understand after three years.

When we are asked why a backend should be built in Go rather than Node, Java or Rust, the answer rarely comes from the benchmarks. Go is fast, yes. But plenty of things are fast. The reason is a different one: Go forces a kind of simplicity you can still read three years later.

The language has few opinions, and that is the opinion

Go has no inheritance, no exceptions, no generics acrobatics, no three ways to write a loop. What looks at first like a shortcoming is a gift in operation: code a junior writes looks almost like code a senior writes. Reviews are about the domain, not about style.

A backend you can no longer read is not a backend any more. It is a mortgage.

For systems meant to run for ten years — and with government, banks and infrastructure that is the rule — readability outweighs any feature list.

Errors are values, not surprises

if err != nil gets its share of eye-rolling. We like it. Every error is a visible path in the code that you either handle or deliberately pass on. There is no stack that surfaces three levels higher and swallows the request quietly.

order, err := repo.FindOrder(ctx, id)
if err != nil {
    return fmt.Errorf("find order %s: %w", id, err)
}

The error chain that results reads in the log like a sentence: handle payment: find order 4711: connection refused. That is observability you do not have to buy a tool for.

One binary, one container, no mystery

Go compiles to a static binary. The deployment is a FROM scratch container with one file in it — no runtime image, no package manager, hardly any attack surface. For Kubernetes environments that means small images, fast starts, little CVE noise. We carry the same pattern into new protocols, for instance when running MCP servers in Go in production. What we offer concretely as Go engineers from Switzerland is on the services page.

Concurrency you can explain

Goroutines and channels are not magic, but they let you write concurrent flows the way you draw them on a whiteboard: a worker pool, a pipeline, a fan-out. Once you have understood the model, you read someone else’s code without fear.

When we do not reach for Go

Honesty belongs here too: for data-heavy exploration and ML pipelines, Python remains the right choice. For frontends, TypeScript obviously. And where a team is already deep in an ecosystem and doing well with it, a change of language is rarely the most important decision available.

But where a system is a company’s critical infrastructure — payments, identity, administration — Go is for us the language that asks the smallest price for clarity.

A conversation, not a newsletter

Let's talk about your system

If this article describes something you recognise, a conversation is the shortest route to an answer.

Let's talk