// back_to_blog Laravel

Building Scalable Laravel Applications: What Actually Matters

Jul 15, 2026 · 3 min read · 3 tags
Building Scalable Laravel Applications: What Actually Matters

Start with the database, not slogans

Most “Laravel is slow” complaints I see are N+1 queries, missing indexes, or loading entire tables into memory. Fix what you can prove is slow before inventing microservices.

1) Kill N+1 queries

Bad:

$posts = Post::all();
foreach ($posts as $post) {
    echo $post->user->name; // query per row
}

Better:

$posts = Post::with('user')->paginate(20);

Use Laravel Debugbar, Telescope, or DB::listen in local to spot repeated queries. Docs: Eager loading.

2) Index what you filter and join

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

Foreign keys and columns in WHERE / ORDER BY are the usual suspects. Do not index everything—writes pay for every index.

3) Push heavy work to queues

php artisan make:job SendInvoiceEmail

class SendInvoiceEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    // handle() ...
}

SendInvoiceEmail::dispatch($invoice);

Run a worker: php artisan queue:work. Use Redis + Horizon when volume justifies it (Horizon docs). Emails, image processing, report exports, and third-party HTTP calls rarely belong in the HTTP request.

4) Cache the expensive bits

$stats = Cache::remember('dashboard.stats', 60, function () {
    return DashboardStats::compute();
});

In production also run:

php artisan config:cache
php artisan route:cache
php artisan view:cache

Invalidate or key caches carefully when underlying data changes. Boring TTLs beat clever wrong caches.

5) Keep structure boring

Thin controllers, Form Requests, policies, service classes for multi-step domain work. Consistency scales better than clever architecture when you maintain the app six months later.

6) Measure before you rewrite

Telescope, slow query logs, and simple APM beat guessing. Fix the endpoint you can prove is slow. Premature microservices usually create more ops work than they remove.

Troubleshooting and common mistakes

Most failures I see are configuration and process issues, not “the framework is broken.” Slow down: reproduce on a clean environment, read the exact error, and change one variable at a time.

  • Confirm you are on the documented major version of the tool you are following.
  • Prefer official docs over random outdated blog snippets when commands disagree.
  • Keep lockfiles committed so teammates and CI install the same dependency graph.
  • Separate “works on my machine” fixes (PATH, SDK licenses, local services) from application bugs.

What to do next

Implement the smallest vertical slice from this article on a throwaway branch, then promote the patterns into your real app. Guides that stay theoretical never catch the auth, env, and deploy footguns that actually burn time.

Horizontal scale without drama

When one app server is not enough: multiple app nodes behind a load balancer, shared Redis for cache/sessions/queues, and a managed MySQL primary (read replicas only after you know your read patterns). Sticky sessions are a crutch—prefer Redis sessions if you scale web nodes.

Do not split into microservices until a bounded context and team boundary demand it. A modular monolith with queues gets most products surprisingly far.

Ops checklist before a traffic spike

  1. Config/route/view caches built in deploy
  2. Queue workers supervised and scaled
  3. Database backups verified
  4. Slow query log sampled on staging with production-like data volume
  5. Rate limits on auth and expensive report endpoints
  6. Error tracking (Sentry or similar) wired with release tags

Enjoyed this article?

Explore more posts or get in touch about a project.