Navigation

Programming

Why My Laravel App Crawled—And How I Fixed It with Smart Queries

I thought Laravel was the slow part—until I realized it wasn’t the framework, but *how* I was querying my database. Here’s how I refactored my queries and added indexes—and brought my app back from the brink in 2025.
Jul 05, 2025
4 min read

Laravel Wasn’t the Problem—My Queries Were

Let me guess: you’re here because your Laravel app is slow.

Yeah, I’ve been there. A few months ago, my app was struggling. Every page load took forever, users started complaining, and I was frantically refreshing Horizon thinking maybe the queue was backed up.

I blamed Laravel. I blamed PHP. I even briefly considered switching to Go.
Spoiler: the problem was none of that.

It was me, and the way I was querying the database.


The “I Know What I’m Doing” Stage (I Didn’t)

At the beginning, things were fast. I was querying like this:

$users = User::all();

No filters, no select(), no limits. Just give me everything. Worked fine with 100 users.

Until it didn’t.


Step 1: Select Only What You Need

Fetching entire tables isn’t brave—it’s lazy.

I updated:

$users = User::all();

to:

$users = User::select('id', 'name', 'email')
             ->where('active', true)
             ->limit(100)
             ->get();

Boom. Instantly snappier response. Smaller payload. Less memory. Huge win.


Step 2: Indexes—The Performance Superpower I Ignored

I had a table called orders with 100K+ rows. I was filtering like this:

$orders = Order::where('customer_id', $id)
               ->where('status', 'pending')
               ->get();

And it was slow.

I finally asked myself: “Did I ever add an index to those fields?”

I hadn’t.

So I did:

Schema::table('orders', function (Blueprint $table) {
    $table->index('customer_id');
    $table->index(['status', 'created_at']);
});

Query time went from seconds to milliseconds.

Lesson: if you’re filtering or ordering by a column often, index it. Full table scans are performance killers.


Step 3: Stop N+1s Before They Multiply

I thought eager loading meant adding ->with() to everything.

Turns out, too much eager loading can be just as bad as none.

This was me:

$posts = Post::with(['user', 'comments', 'tags', 'likes', 'views', 'categories'])->get();

Which triggered a storm of queries.

I cut it down to what the page actually used:

$posts = Post::with(['user', 'comments'])->paginate(20);

Laravel Debugbar showed fewer queries, lower memory, faster render. Less is more.


Step 4: Use chunk() or cursor() for Large Jobs

Once, I ran this on a cron job:

$users = User::all();
foreach ($users as $user) {
    // process...
}

It worked until we hit 50K users. Then it killed the memory.

I replaced it with:

User::chunk(1000, function ($users) {
    foreach ($users as $user) {
        // process...
    }
});

Or sometimes:

DB::table('logs')->orderBy('id')->cursor()->each(function ($log) {
    // process...
});

Memory-safe, efficient, reliable. Perfect for batch tasks.


Bonus: Use Query Logging and Telescope Like a Detective

I started using DB::enableQueryLog() and Laravel Telescope to spy on what was really happening.

Sometimes it wasn’t my code—it was third-party packages making queries I didn’t know about.

Other times? It was me. Writing messy joins. Forgetting pagination. Being careless.

Seeing actual queries made me smarter.


Summary: What I Learned

Tip Why It Matters
✅ Use select() + limit() Reduce data size and memory
✅ Add proper indexes Speed up frequent filters and lookups
✅ Avoid unnecessary eager loading Prevent memory bloat and extra queries
✅ Use chunk() or cursor() Handle large datasets safely
✅ Profile queries with Telescope Find hidden performance issues

Laravel Isn’t Slow—But Your Queries Might Be

After applying these changes, my app felt new again. Same codebase. Same hosting. Just better queries.

So if you’re about to give up on Laravel… maybe don’t. Look at your database. Look at your queries. Look at how you’re loading data.

Because the truth is: Laravel can fly—if you let it.


Have your own performance war story? Drop it in the comments. Let’s help each other build better. 🚀

Share this article

Add Comment

No comments yet. Be the first to comment!

More from Programming