DEV Community

ekko1500
ekko1500

Posted on

How I Solved Slow Page Loading Using the N+1 Query Fix (React + Laravel)

When I first built my React + Laravel application, everything worked fine—until the data started growing.

Pages that used to load instantly began taking seconds. Then even longer.

At first, I thought it was a frontend issue. Maybe React was re-rendering too much. Maybe my components weren’t optimized.

I was wrong.

The real problem was happening in the backend—and it had a name: the N+1 query problem.


The Problem I Didn’t See at First

Let’s say I had something like this in my Laravel backend:

  • A list of students
  • Each student has marks
  • Each mark belongs to a subject

Simple, right?

But here’s what actually happened when I fetched data:

1 query to get students
Then N queries to get each student's related data

So if I had 100 students, I was running:
👉 101 queries

That’s the N+1 problem.

And it destroyed performance.


How I Discovered It

I started debugging the backend and noticed something strange:

  • The API response time was slow
  • Database queries were increasing with data size

So I used Laravel debugging tools and logs.

That’s when I saw it clearly:
👉 Queries were being executed inside loops

That’s the moment it clicked.


The Fix: Eager Loading

Laravel already has a solution for this: Eager Loading

Instead of fetching related data one-by-one, I loaded everything in a single query.

Before (Bad)

$students = Student::all();

foreach ($students as $student) {
    echo $student->marks; // triggers query every time
}
Enter fullscreen mode Exit fullscreen mode

After (Good)

$students = Student::with('marks')->get();
Enter fullscreen mode Exit fullscreen mode

Now:

  • Only 2 queries total
  • No matter how many students

Massive improvement.


Going Deeper: Nested Relationships

My case wasn’t that simple.

I had deeper relationships like:

  • students → marks → subjects

So I used nested eager loading:

$students = Student::with('marks.subject')->get();
Enter fullscreen mode Exit fullscreen mode

Now everything loads efficiently in minimal queries.


Optimizing the API Response

Fixing queries wasn’t enough.

I also improved how data was sent to React.

What I changed:

  • Removed unnecessary fields
  • Used API Resources (Transformers)
  • Sent only what the UI actually needs
return StudentResource::collection($students);
Enter fullscreen mode Exit fullscreen mode

This reduced payload size and improved speed.


React Side Optimization

After fixing Laravel, I improved React too.

1. Avoid Unnecessary Re-renders

I used:

  • useMemo
  • useCallback
  • Proper state structure

2. Lazy Loading Components

const Dashboard = React.lazy(() => import('./Dashboard'));
Enter fullscreen mode Exit fullscreen mode

This reduced initial load time.

3. Efficient Data Fetching

  • Avoided duplicate API calls
  • Cached results when possible

The Result

After all optimizations:

  • Page load time dropped significantly
  • API became faster and more scalable
  • UI felt instant even with large data

What used to feel slow and heavy became smooth and responsive.


What I Learned

This experience taught me something important:

Performance problems are often not where you think they are.

I spent time looking at React—but the real issue was in the database.


Key Takeaways

  • Always watch for N+1 queries in backend systems
  • Use Eager Loading in Laravel (with())
  • Optimize API responses, not just queries
  • Frontend performance depends on backend efficiency

Final Thoughts

Fixing the N+1 query problem completely changed how I think about building applications.

Now, whenever I design a feature, I ask:

👉 How many queries will this run?

Because performance isn’t just about code—it’s about how systems interact.

And once you fix the root problem, everything becomes faster.

Top comments (0)