Advertisement
webdev Is your Laravel or Node.js API slow? Here’s a real-world debugging guide showing why APIs become slow and how to fix them using caching, database optimizations, and performance tuning.

How I Fixed a Slow API Response Time in Laravel & Node.js

5 Min Read Verified Content

🛑 The Problem — “Why Is My API So Slow?”

A client once contacted me with a frustrated tone:

“Our mobile app API is getting slower every day. Sometimes it takes 6–10 seconds just to load a simple list.”

Six to ten seconds might not sound huge — but in web performance terms, that’s an eternity. Users think the app is broken. Support tickets start pouring in. And yes… Google also hates slow APIs.

The stack was:

• Backend: Laravel API
• Secondary Service: Node.js microservice
• Database: PostgreSQL

At first glance, everything looked fine.

But clearly… something wasn’t.

So I rolled up my sleeves and started investigating.


🔍 Step 1 — Confirm the Problem (Never Assume)

Before changing anything, I always measure first.

I used:

Postman → View response time Browser Network tab → Timing Laravel Telescope → request profiling

Sure enough…

• Some endpoints were fast (80–150ms)
• But others took 2–10 seconds

So the API was not globally slow — only some routes.

That’s good news, because it means the problem is isolated.


🕵️ Step 2 — Find the “Slow” Endpoint

The slow endpoint was:

GET /api/orders

It returned a list of user orders with product data included.

The problem smelled like a database issue.

So I ran a query log.

In Laravel:

\DB::enableQueryLog(); $orders = Order::with('product')->where('user_id', $id)->get(); dd(\DB::getQueryLog());

The result shocked me.

❌ There were hundreds of queries running

Why?

Because this line was triggering N+1 queries:

Order::with('product')

But the relationship in the model used:

public function product() { return $this->hasOne(Product::class); }

Except…

The real relationship was belongsTo, not hasOne.

So eager loading didn’t work correctly.

Meaning:

• Fetch orders
• Loop orders
• Fetch product each time
• One request = 300+ database calls

No wonder it crawled.


🛠 Step 3 — Fix the Relationship

I opened the Order.php model and changed it.

From ❌ (wrong)

public function product() { return $this->hasOne(Product::class); }

To ✅ (correct)

public function product() { return $this->belongsTo(Product::class); }

Then I tested again.

Boom.

Queries dropped from 312 to 2.

Response time dropped from 6.4 seconds → 140ms.

But we didn’t stop there.


⚡ Step 4 — Add Caching (Because Users Love Speed)

Even with optimization, orders don’t change every second.

So I cached the result.

$orders = Cache::remember("orders_{$userId}", 60, function() use ($userId) { return Order::with('product') ->where('user_id', $userId) ->get(); });

Now:

• First request = database fetch
• Next 60 seconds = lightning fast

The endpoint now averaged 40–60ms consistently.

That’s the difference between users smiling and rage-quitting.


🔄 Step 5 — Check the Node.js Service Too

The Node.js service fetched product stats.

I found a similar issue:

They were recomputing heavy analytics on every request.

So we added:

const NodeCache = require("node-cache"); const cache = new NodeCache({ stdTTL: 60 }); app.get("/product/stats", async (req, res) => { const cached = cache.get("stats"); if (cached) return res.json(cached); const stats = await getStatsFromDb(); cache.set("stats", stats); res.json(stats); });

CPU dropped. Response time stabilized.


🧠 Step 6 — Final Checks

Before declaring victory, I always:

✔ Load-test with 100+ concurrent calls
✔ Monitor CPU / DB usage
✔ Enable slow-query logs
✔ Add index if needed

Performance now remained consistent.

Crisis averted.


🎯 Key Lessons Learned

This wasn’t magic. Just systematic debugging.

Here’s what mattered most:

✅ Measure before guessing

Don’t “feel” performance. Prove it with numbers.

✅ N+1 Queries kill performance

Always check relationships in Laravel.

✅ Caching solves real-world latency

But do it intentionally. Avoid stale data.

✅ Node.js also benefits from caching

Especially expensive computations.

✅ Monitor production

Logs are your best friend.


💬 Final Thoughts

Performance optimization is rarely about rewriting everything.
Most of the time, it’s about:

• fixing small mistakes
• improving database usage
• reducing redundant work

And yes, slow APIs can be fixed — without stress.

Advertisement
Back to Webdev