Engineering Note
How we scaled a Ruby on Rails app without moving to microservices
Sharing some insights from a scaling decision we faced in production.
Let me explain how we scaled a Rails app without moving to microservices.
At one point, traffic was growing and things started slowing down.
Not a full system failure.
Just specific pain points.
If we look closely, the issues were not about scale itself:
- Requests were doing too much work
- Background jobs were competing with user traffic
- Reports were hitting the same database as core APIs
So naturally, the question came:
“Should we move to microservices?”
But here is what we realised.
The system was not too big.
It was just not well separated.
Instead of breaking it apart, we focused on behaviour:
We moved long-running work completely out of the request cycle.
We separated read-heavy operations from transactional flows.
We defined clear boundaries inside the monolith.
Same codebase.
Better structure.
After that, things stabilised.
Performance improved.
Deployments stayed simple.
No added complexity of distributed systems.
So the takeaway is simple.
Scaling problems don’t always need new architecture.
Sometimes they need better discipline inside the existing one.
That’s what worked for us.
Let me explain how we scaled a Rails app without moving to microservices.
At one point, traffic was growing and things started slowing down.
Not a full system failure.
Just specific pain points.
If we look closely, the issues were not about scale itself:
- Requests were doing too much work
- Background jobs were competing with user traffic
- Reports were hitting the same database as core APIs
So naturally, the question came:
“Should we move to microservices?”
But here is what we realised.
The system was not too big.
It was just not well separated.
Instead of breaking it apart, we focused on behaviour:
We moved long-running work completely out of the request cycle.
We separated read-heavy operations from transactional flows.
We defined clear boundaries inside the monolith.
Same codebase.
Better structure.
After that, things stabilised.
Performance improved.
Deployments stayed simple.
No added complexity of distributed systems.
So the takeaway is simple.
Scaling problems don’t always need new architecture.
Sometimes they need better discipline inside the existing one.
That’s what worked for us.