Why Go and not Python?

Why Go and not Python?

By Nils Marti, CTO
#development#backend#go

Why We Chose Go over Python for LearningLevels

When we first started developing LearningLevels, our team naturally gravitated toward Python. It's friendly, readable, and backed by a huge ecosystem — especially in the web space with frameworks like FastAPI. For our first proof of concept, we even had a couple of microservices up and running using FastAPI.

But as we started preparing for production, we ran into a few challenges:

🚧 Performance Matters — Even for Education Platforms

FastAPI is great, but Python's single-threaded performance was becoming a bottleneck as we started simulating classroom-scale workloads. For example, scoring hundreds of free-text answers in real time started lagging. While Python has tools like asyncio, we found that concurrency and memory usage quickly became complex to manage at scale.

🐋 Slimmer, Faster Containers with Go

Another unexpected pain point was Docker image size. Our Python-based services required heavy base images, dependencies like uvicorn, and even OS-level packages. The resulting containers were large, slow to build, and added friction to our CI/CD pipelines.

Switching to Go allowed us to:

  • Use multi-stage builds to produce tiny final images with no runtime dependencies.

  • Compile everything down to a single static binary.

  • Cut cold start times and reduce memory usage significantly.

🔁 Our Migration

The rewrite wasn’t trivial, but it gave us a chance to rethink some APIs, simplify error handling, and unify logging and observability practices across services. In the end, it made our backend more robust, maintainable, and future-proof.

📌 Takeaway

FastAPI served us well to get started, but Go gave us the performance, reliability, and operational simplicity we needed to scale LearningLevels for real-world classrooms.

This post is part of a short series about technical decisions behind LearningLevels. Stay tuned!