Why I Use Go for Distributed Systems (And Python for Everything Else)
After working with both Go and Python across very different problem spaces, here's how I think about choosing between them — and when I reach for each one.
The question I get asked
"If you already know Python, why bother with Go?"
It's a fair question. Python is expressive, has a massive ecosystem, and can run a web server, train a neural network, and scrape a website in the same afternoon. So why learn a language that lacks generics (well, until 1.18), has no exceptions, and makes you explicitly handle every error?
Because they solve different problems, and pretending otherwise leads to real pain in production.
What Go is actually good at
Go is not better than Python. It's better at a specific class of problems: long-running networked services where predictable performance, explicit concurrency, and small resource footprint matter.
When I work on Vault, these properties matter a lot:
- A Vault server runs for months. Memory management needs to be predictable, not subject to GC pressure spikes at 3am.
- A Vault request might touch multiple backends, validate tokens, and write to a Raft log — all under a timeout. Goroutines + channels make this composable without threading hell.
- A single Vault binary is deployed to many environments. A single static binary with no runtime dependency is a massive operational win.
Python's GIL, its dynamic memory model, and its "everything is an object" philosophy are not bugs — they're tradeoffs that make it excellent for other use cases. But for a secrets daemon that needs to handle 10,000 concurrent requests without blinking, Go wins cleanly.
What Python is actually good at
ML, data pipelines, scripting, and rapid experimentation. Full stop.
When I'm exploring a computer vision idea, the speed of iteration that Python's ecosystem gives you is unmatched:
# From idea to working prototype in ~20 lines
import torch
import torchvision.models as models
model = models.resnet50(pretrained=True)
model.eval()
# Swap the head for fine-tuning
model.fc = torch.nn.Linear(model.fc.in_features, num_classes)
Try writing the equivalent PyTorch training loop in Go. You can, but you'd spend most of your time fighting the type system where Python just... works.
My actual heuristic
| Problem | Language | |---|---| | Long-running daemon / server | Go | | CLI tool with complex logic | Go | | ML model training / research | Python | | Data pipeline / ETL | Python | | Quick script / automation | Python | | Anything touching gRPC in production | Go |
The interesting cases are at the edges — inference servers, ML at the infrastructure layer, embedding models into Go services. That's where I spend a lot of side-project time.
The real skill
The real skill isn't mastering one language — it's knowing which tool to reach for and why. Using Go for a weekend data cleaning script is masochism. Using Python to write a distributed consensus algorithm is a debugging nightmare.
Both ecosystems have matured enormously. Use the right one.