Skip to content
Journal

Why we left Laravel for Go

An overloaded server is what made us start looking for an alternative. But what kept us with Go ever since turned out to have nothing to do with that.

Written

An overloaded server is what made us start looking for an alternative. But what kept us with Go ever since turned out to have nothing to do with that.

Before building Merlin, we'd already worked with Laravel for quite a while.

Across several projects, the same pattern: once things started growing, the server became the bottleneck — something we ran into almost every time the load went up.

What was on our minds then was simple: find something lighter, something that would keep the server calm even as traffic climbed.

Thinking it was just about weight

That's where the search began.

At the time, the assumption was simple: find something lighter than Laravel, problem solved.

Node.js and NestJS topped the list first. The reason was practical — we were already familiar with the JavaScript ecosystem, so it looked like the most sensible choice.

On paper, every box was checked. Lighter than Laravel, a large ecosystem, and one we'd already mastered.

If it was just about weight, why the hesitation

But every time we seriously considered Node, something felt off.

We dug further, and it turned out Node's overhead was roughly on par with the Laravel we were trying to leave.

If the reason was really just about weight, the problem should have been solved at this point — Node was light enough, we already knew the ecosystem, all that was left was to switch.

Yet the hesitation stayed.

The turning point

It took time to realize why.

What was bothering us turned out to be the working approach itself — there was still one large layer deciding how our code had to be structured, before we ourselves got to decide.

All along, we thought we were looking for a lighter stack.

What we actually found was a way of working that genuinely felt like our own: a way of working we arranged ourselves to fit the product's needs, in a place a framework would usually have already decided for us.

The question changed at that point, from "which one is lighter" to "what approach is most comfortable for building Merlin."

Once the question changed, the answer changed with it.

What we finally found: Go

Among the options we looked at then, Go felt closest to what we were looking for.

Its speed and reputation were just a bonus that became more apparent later.

What made Go stick was its simplicity. The system's flow became easier to follow, because most of the decisions live in the code we wrote ourselves — that's also where debugging starts.

Every dependency we used was also chosen deliberately, one at a time, to match the system's needs.

The price we paid

This decision also came at a cost.

Leaving a framework behind meant we also had to rebuild every small thing it would normally have provided for free — battle-tested validation, security patterns someone else had already thought through.

We felt some of that ourselves later, in the form of mistakes we had to fix after Merlin was already running.

That's a long story, and deserves a post of its own — not this one.

What's lasted until now

The overloaded server is what made us start searching.

What we found at the end of that search turned out to be a completely different matter.

The stack we use changed. How we think about the code we write changed with it — from simply looking for something that fits on a server, to looking for a way of working that genuinely feels like our own.

The problem that got us moving isn't the reason we've stayed on this path.

Category: Build