Blog

How to find the real bottleneck in a slow Rails app

Most Rails apps don’t become slow overnight.
They degrade slowly…
until one day:
  • APIs start timing out
  • background jobs pile up
  • users complain about “random slowness”
And the usual reaction is:
“Let’s scale the server”
“Add more workers”
“Upgrade the DB instance”
Sometimes that works.
Most times, it just hides the real problem.
The real issue
In most cases, the bottleneck is not where you think it is.
It’s not always:
  • the database
  • the server
  • or even Rails
It’s usually:
👉 a specific part of the system under specific conditions

Step 1: Don’t guess. Measure.
Before changing anything, you need visibility.
Start with:
  • Request timing (controller/action level)
  • DB query time
  • External API latency
  • Background job queue time
Tools that help:
  • APM tools (New Relic, Datadog, Skylight)
  • Rails logs (yes, still useful)
  • Custom instrumentation if needed
👉 Goal: break one request into pieces
Total request time = DB + app logic + external calls + rendering

Until you see this breakdown, you’re guessing.

Step 2: Identify the slowest layer
Once you have data, ask:
👉 Where is the time actually going?
Common patterns:
1. DB-heavy requests
  • High query time
  • Many queries per request
Usually:
  • N+1 queries
  • missing indexes
  • large scans
2. CPU-heavy logic
  • Low DB time but high total time
Usually:
  • heavy Ruby processing
  • JSON building
  • complex loops
3. External dependency bottleneck
  • Calls to APIs slowing everything down
Usually:
  • payment gateways
  • third-party services
  • internal microservices
4. Background job backlog
  • Requests fast, but system still feels slow
Usually:
  • Sidekiq queues backed up
  • jobs not processed fast enough
Step 3: Reproduce under real conditions
One of the biggest mistakes:
👉 Testing locally and assuming it reflects production
It doesn’t.
You need to:
  • test with production-like data
  • simulate concurrent traffic
  • observe behaviour under load
Sometimes a query is fast with 1k records
…but breaks at 1M.

Step 4: Look for amplification, not just slowness
A small inefficiency becomes a big problem at scale.
Example:
  • One extra query → fine
  • 100 extra queries per request → disaster
This is where Rails apps usually fail:
👉 multiplication effects
Things to check:
  • N+1 queries
  • repeated API calls
  • redundant computations
Step 5: Fix the right thing (not everything)
Once you find the bottleneck:
Don’t refactor the whole system.
Fix:
👉 the highest-impact issue first
Examples:
  • Add missing index → huge improvement
  • Cache a heavy computation → instant win
  • Batch background jobs → queue clears
Step 6: Validate the improvement
After fixing:
  • Measure again
  • Compare before vs after
  • Ensure no side effects
👉 If you don’t measure, you don’t know if it worked
What I’ve seen in production
In most Rails systems I’ve worked on:
  • 80% of performance issues come from:
    • bad queries
    • missing indexes
    • inefficient job processing
  • Not from:
    • Rails itself
    • server capacity
Final thought
Scaling a Rails app is not about adding more infrastructure.
It’s about:
👉 removing the real bottleneck
Once you fix that, everything else becomes easier.
If your app feels slow…
Don’t start with scaling.
Start with:
👉 understanding where the time is actually going
That’s where the real fix is.