“Go or Rust?” is one of those questions that starts long threads and ends nowhere. Benchmarks get posted. Someone mentions memory safety. Someone else mentions compile times. Nobody changes their mind.
We use both, and we stopped having that argument a while ago. The rule we wrote down earlier in why we build with Go, Flutter and Rust still holds. This post is the practical side of it: the actual projects, and the question that decided each one.
That question turned out to be simple. Where will this code live?
If it runs on its own, it’s Go
Most of what we build behind an app is a service. It sits on a server, listens for requests, talks to a small database, and has to keep doing that for years without anyone looking at it. For that job we pick Go every time.
Some real cases:
- A sync server for a to-do app. People can host it themselves, on their own machine. So it has to be easy to run for someone who is not us. It ships as one small program in an otherwise empty container. No runtime to install, no extra packages, nothing to update except the program itself.
- A self-hosted analytics tool for our store sales. It reads App Store and Google Play numbers and shows them on our own server instead of a third-party dashboard. It is open source, so anyone can run it on their own box. Same story: small, quiet, boring to deploy.
- A price cache for a crypto portfolio app. It fetches prices once and serves them to the apps from our own server. It needs exactly two outside libraries.
- An SSH login monitor. It runs on a Linux server, sends an alert the moment someone logs in, and a morning report of every failed attempt. Open source too.
Look at what these have in common. None of them does heavy math. They spend most of their life waiting: for the network, for the disk, for the next request. What matters is that they start fast, use little memory, are easy to read a year later, and do not drag in a long list of other people’s code.
That last point matters more to us than speed. Our services have a short list of direct dependencies, usually under ten and often five or fewer. Every library you add is code you did not write and have to trust. Go’s standard library covers so much (web server, crypto, JSON, testing) that a short list is the normal case, not a discipline you have to fight for.
If it lives inside the app, it’s Rust
Rust shows up for a different job: code that has to run inside our Flutter apps, on every device the app supports.
Our clearest case is a file sync library. The idea: an app keeps its data as plain files in a private git repository that the user owns, and syncs it with their own server over SSH. No cloud account, no company in the middle. The library handles cloning, syncing, picking the newer version when two devices changed the same file, and creating the SSH key on the device, with a 12-word recovery phrase so the user can get the key back.
That library has to run on Android, iOS, macOS, Windows and Linux. From the same code. Inside an app that is already running.
This is where Rust fits naturally:
- It builds into a library that other programs load. A Flutter app calls it like any other package. That is Rust’s home ground; Go’s home ground is a program that runs by itself.
- The serious tools already exist. Rust has mature libraries for working with git repositories and SSH. Writing those from scratch would be months of work and a security risk.
- It handles the sensitive part on the device. Keys are created on the phone and never leave it. That is a privacy rule for us, and Rust lets us keep that code small and strict.
Honest note: this library is still a prototype. It works, but it is not yet inside a shipped app. We’d rather say that than pretend.
Why not the other way around?
People sometimes ask why we don’t write the servers in Rust too, since it can do that job. It can. We’d reach for it the day a service has a truly heavy workload, where every millisecond of computing matters. None of ours has needed that yet. A sync server that waits on the network does not get faster with a different language. It just gets a longer build.
And why not put Go inside the apps? It is possible, but that is not what we use Go for, and Rust already does that job well. When a tool is clearly built for a job, we use that tool and skip the clever workaround.
So it’s not “Go is better” or “Rust is better.” Each one is very good at its own job. Picking by location keeps us from using either one for the wrong job.
What about AI-written code?
We write a lot of code together with AI tools, so this question matters to us.
Both languages hold up well, for different reasons. Go code is plain. There is usually one obvious way to write something, so when a model writes a Go handler, a human can review it in minutes. Rust is the opposite kind of help: the compiler is so strict that a lot of mistakes never get as far as review. We wrote about that side in why Rust suits AI-written code.
In practice that matches the split above. Services change often, so we want code that is fast to read. The in-app library changes rarely and touches keys and user files, so we want the compiler to be as picky as possible.
The short version
If you are choosing for your own project, try our question before you read another benchmark:
- Runs by itself on a server, mostly waiting on network and disk? Go. You get a small program that is easy to deploy, easy to read and has few dependencies.
- Has to live inside an app, on several platforms, doing sensitive or heavy work? Rust.
- Neither? You probably don’t need either one yet. Keep it simple until the product asks for more.
The language matters less than people think. Putting the code in the right place matters more.