{"id":7234,"date":"2022-05-11T12:33:58","date_gmt":"2022-05-11T12:33:58","guid":{"rendered":"https:\/\/www.icoderzsolutions.com\/blog\/?p=7234"},"modified":"2026-03-31T16:09:09","modified_gmt":"2026-03-31T10:39:09","slug":"laravel-performance-optimization-guide","status":"publish","type":"post","link":"https:\/\/www.icoderzsolutions.com\/blog\/laravel-performance-optimization-guide\/","title":{"rendered":"Laravel Performance Optimization Guide for 2026"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">Laravel is one of the most widely used PHP frameworks for building modern web applications. As applications grow, performance gaps compound. Slow queries, untuned caches, synchronous heavy tasks, and framework bootstrapping overhead all add latency. This guide covers the optimizations that actually move the needle \u2014 written from production experience. Visit our <\/span><a href=\"https:\/\/www.icoderzsolutions.com\/laravel-development.shtml\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Laravel Development Services<\/span><\/a><span style=\"font-weight: 400;\"> to learn how iCoderz helps teams architect high-performance Laravel systems.<\/span><\/p>\n<h2><b>Why Laravel Performance Optimization Matters<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Slow backend systems cost real money. Degraded API response times increase infrastructure spend, reduce conversion rates, and erode user trust. For SaaS platforms, marketplaces, and delivery apps \u2014 categories where iCoderz regularly architects Laravel backends \u2014 even 200ms of unnecessary latency compounds across millions of requests.<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Higher server costs from inefficient query patterns<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Reduced throughput under traffic spikes<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Slower time-to-first-byte hurting SEO rankings<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Poor mobile UX on high-latency connections<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">Optimization is not a single pass \u2014 it is an ongoing discipline built into architecture from day one.<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<h3><b>1<\/b><\/h3>\n<\/td>\n<td>\n<h3><b>Production Optimization Commands<\/b><\/h3>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">Laravel ships with Artisan commands that cache framework components. Running these at deploy time is table stakes \u2014 it belongs in every CI\/CD pipeline.<\/span><\/p>\n<p><b>Cache configuration files<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\"># Merge all config files into one cached file<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">php artisan config:cache<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><b>Cache application routes<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\"># Compiles routes to a serialized PHP file<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\"># Note: routes using Closures cannot be cached<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">php artisan route:cache<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p><b>Precompile Blade views<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">php artisan view:cache<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p><b>Clear all caches on deploy<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">php artisan optimize:clear<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td><b>Gotcha<\/b><\/p>\n<p><span style=\"font-weight: 400;\">route:cache will silently fail if any route uses a Closure instead of a controller method. Always use controller-based routing in production.<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<h3><b>2<\/b><\/h3>\n<\/td>\n<td>\n<h3><b>Database Query Optimization<\/b><\/h3>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">Database queries are the most common performance bottleneck in Laravel applications. Most of the time the issue is not the database \u2014 it is the Eloquent layer generating more queries than necessary.<\/span><\/p>\n<p><b>Eliminate the N+1 problem with eager loading<\/b><\/p>\n<p><span style=\"font-weight: 400;\">The classic N+1 issue occurs when a relationship is lazy-loaded inside a loop, generating one query per record.<\/span><\/p>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ &#x274c; N+1 \u2014 one query per post<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">$posts = Post::all();<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">foreach ($posts as $post) { echo $post-&gt;comments-&gt;count(); }<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ &#x2705; Eager load \u2014 2 queries total<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">$posts = Post::with(&#8216;comments&#8217;)-&gt;get();<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ &#x2705; Even better when you only need the count<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">$posts = Post::withCount(&#8216;comments&#8217;)-&gt;get();<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td><b>Advanced<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Eager loading also applies inside service classes. Calling $user-&gt;load(&#8216;orders&#8217;) inside a loop is the same N+1 problem. Use loadMissing() defensively or pre-load in the controller.<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><b>Select only the columns you need<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ &#x274c; Fetches every column<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">User::all();<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ &#x2705; Only what the view needs<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">User::select(&#8216;id&#8217;, &#8216;name&#8217;, &#8217;email&#8217;)-&gt;get();<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ &#x2705; Subquery selects for derived data<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">User::addSelect([<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 &#8216;latest_order_at&#8217; =&gt; Order::select(&#8216;created_at&#8217;)<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 \u00a0 \u00a0 -&gt;whereColumn(&#8216;user_id&#8217;, &#8216;users.id&#8217;)<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 \u00a0 \u00a0 -&gt;latest()-&gt;take(1)<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">])-&gt;get();<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p><b>Paginate large result sets<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ paginate() \u2014 sends COUNT + data query<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">User::paginate(20);<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ simplePaginate() \u2014 no COUNT, faster for large tables<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">User::simplePaginate(20);<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ cursorPaginate() \u2014 keyset pagination, O(1) at any offset<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">User::cursorPaginate(20);<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<h3><b>3<\/b><\/h3>\n<\/td>\n<td>\n<h3><b>Processing Large Datasets Efficiently<\/b><\/h3>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">Loading 500,000 records into a PHP array will exhaust memory. Laravel gives you two tools \u2014 understand the difference and pick the right one.<\/span><\/p>\n<p><b>chunk() \u2014 batched processing<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ Loads N rows at a time into memory<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ Good for write operations<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">User::chunk(100, function ($users) {<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 foreach ($users as $user) {<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 \u00a0 \u00a0 $user-&gt;update([&#8216;score&#8217; =&gt; computeScore($user)]);<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 }<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">});<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><b>cursor() \u2014 one record at a time<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ Uses a PDO server-side cursor \u2014 memory stays flat<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ Best for read-only pipelines: exports, reports, analytics<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">foreach (User::cursor() as $user) {<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 $this-&gt;export-&gt;write($user);<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">}<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td><b>Key Difference<\/b><\/p>\n<p><span style=\"font-weight: 400;\">chunk() runs batched SELECT queries and loads N Eloquent models into memory at once. cursor() yields one model at a time via a real database cursor \u2014 memory is O(1). For write-heavy operations use chunk(). For read-only pipelines, cursor() is almost always better.<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<h3><b>4<\/b><\/h3>\n<\/td>\n<td>\n<h3><b>Database Indexes<\/b><\/h3>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">A missing index on a high-traffic table will kill performance faster than any amount of PHP optimization. Index columns used in WHERE, JOIN, and ORDER BY clauses. For <\/span><span style=\"font-weight: 400;\">large custom software projects<\/span><span style=\"font-weight: 400;\"> at iCoderz, careful index design is often the difference between a system that handles 10x growth gracefully and one that requires emergency scaling.<\/span><\/p>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ Single column<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">$table-&gt;index(&#8217;email&#8217;);<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ Composite \u2014 column order matters.<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ Put the equality column first.<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">$table-&gt;index([&#8216;status&#8217;, &#8216;created_at&#8217;]);<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ For: WHERE status = ? ORDER BY created_at DESC<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ The above composite handles both filter and sort in one scan<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ Partial index (MySQL 8+ \/ Postgres)<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ Only index active records \u2014 smaller, faster<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">DB::statement(<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 &#8216;CREATE INDEX idx_active ON orders(user_id) WHERE deleted_at IS NULL&#8217;<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">);<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<h3><b>5<\/b><\/h3>\n<\/td>\n<td>\n<h3><b>Caching Strategies<\/b><\/h3>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">Caching is not just &#8216;store the query result for an hour.&#8217; Done properly it dramatically reduces database load while keeping data fresh enough to be correct.<\/span><\/p>\n<p><b>Basic cache-aside pattern<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">$users = Cache::remember(&#8216;users.active&#8217;, 3600, function () {<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 return User::where(&#8216;status&#8217;, &#8216;active&#8217;)-&gt;get();<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">});<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p><b>Atomic locks \u2014 prevent cache stampedes<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ Without a lock, 50 concurrent misses = 50 DB queries<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">$lock = Cache::lock(&#8216;users.active.lock&#8217;, 10);<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">if ($lock-&gt;get()) {<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 $users = User::where(&#8216;status&#8217;, &#8216;active&#8217;)-&gt;get();<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 Cache::put(&#8216;users.active&#8217;, $users, 3600);<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 $lock-&gt;release();<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">}<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p><b>Cache invalidation<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ Forget a key on model update<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">Cache::forget(&#8216;users.active&#8217;);<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ Tagged cache \u2014 flush an entire group at once<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">Cache::tags([&#8216;users&#8217;])-&gt;flush();<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ Model observer \u2014 auto-invalidate on save\/delete<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">class UserObserver {<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 public function saved(User $user): void {<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 \u00a0 \u00a0 Cache::tags([&#8216;users&#8217;])-&gt;flush();<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 }<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">}<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td><b>When NOT to cache<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Avoid caching write-heavy tables where stale reads cause logical errors \u2014 inventory counts, balance figures, seat availability. Cache read-heavy, slow-changing data: categories, config, product listings.<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td><b>Need a caching architecture review?<\/b><\/p>\n<p><span style=\"font-weight: 400;\">iCoderz engineers have designed Redis-backed caching layers for high-traffic SaaS platforms and marketplaces. We can audit your current setup and identify the highest-impact changes.<\/span><\/p>\n<p><a href=\"https:\/\/icoderzsolutions.com\/contact.php\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">Talk to a Laravel expert \u2192 icoderzsolutions.com\/laravel-development<\/span><\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<h3><b>6<\/b><\/h3>\n<\/td>\n<td>\n<h3><b>Redis for High-Performance Applications<\/b><\/h3>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">Redis is not just a cache driver \u2014 it is a complete in-memory data platform. In a production Laravel stack, Redis typically handles caching, session storage, queue brokering, and rate limiting simultaneously.<\/span><\/p>\n<p><b>Configure all drivers in .env<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">CACHE_DRIVER=redis<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">SESSION_DRIVER=redis<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">QUEUE_CONNECTION=redis<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><b>Sorted Sets for leaderboards and ranked data<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ O(log N) insert + O(log N) range queries<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ Perfect for leaderboards, top-N feeds, score rankings<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">Redis::zadd(&#8216;leaderboard&#8217;, $score, $userId);<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">$top10 = Redis::zrevrange(&#8216;leaderboard&#8217;, 0, 9, [&#8216;withscores&#8217; =&gt; true]);<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p><b>Rate limiting<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">RateLimiter::for(&#8216;api&#8217;, function (Request $request) {<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 return Limit::perMinute(60)<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 \u00a0 \u00a0 -&gt;by($request-&gt;user()?-&gt;id ?: $request-&gt;ip());<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">});<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<h3><b>7<\/b><\/h3>\n<\/td>\n<td>\n<h3><b>Queues for Background Processing<\/b><\/h3>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">Any operation that does not need to complete before the HTTP response should be queued. This is not optional in high-traffic applications \u2014 it is an architectural discipline.<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ &#x274c; Blocks the request \u2014 user waits for email to send<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">Mail::to($user)-&gt;send(new WelcomeMail($user));<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\/\/ &#x2705; Returns immediately \u2014 worker handles it async<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">Mail::to($user)-&gt;queue(new WelcomeMail($user));<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><b>Prevent duplicate jobs<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">class ProcessReport implements ShouldQueue, ShouldBeUnique {<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 public function uniqueId(): string {<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 \u00a0 \u00a0 return &#8220;report-{$this-&gt;reportId}&#8221;;<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 }<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">}<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><b>Start and manage workers<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">php artisan queue:work<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\"># Inspect failed jobs<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">php artisan queue:failed<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\"># Retry all failed jobs<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">php artisan queue:retry all<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">In production, run workers under Supervisor for automatic restarts. For serious workloads, <\/span><span style=\"font-weight: 400;\">Laravel Horizon<\/span><span style=\"font-weight: 400;\"> gives you real-time monitoring, throughput metrics, and fine-grained queue balancing.<\/span><\/p>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<h3><b>8<\/b><\/h3>\n<\/td>\n<td>\n<h3><b>PHP OPcache<\/b><\/h3>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">PHP compiles source code to bytecode on every request \u2014 unless OPcache is enabled. OPcache stores compiled bytecode in shared memory, eliminating the compilation step entirely.<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">; Recommended production configuration<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">opcache.enable=1<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">opcache.memory_consumption=256<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">opcache.max_accelerated_files=20000<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">opcache.validate_timestamps=0 \u00a0 ; Disable in production<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">opcache.revalidate_freq=0<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td><b>Critical Deploy Gotcha<\/b><\/p>\n<p><span style=\"font-weight: 400;\">With validate_timestamps=0, deploying new PHP files does NOT invalidate OPcache automatically. You must restart PHP-FPM or call opcache_reset() in your deploy hook. This is the most common cause of &#8216;why is my old code still running?&#8217; after a deployment.<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<h3><b>9<\/b><\/h3>\n<\/td>\n<td>\n<h3><b>Laravel Octane<\/b><\/h3>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">Standard PHP-FPM bootstraps the entire Laravel framework for every single request. Octane eliminates this by booting the application once and keeping it in memory across requests. Combined with Swoole or RoadRunner, it can deliver 5\u201310x throughput improvements. Ideal for <\/span><a href=\"https:\/\/www.icoderzsolutions.com\/php-development.shtml\" target=\"_blank\" rel=\"noopener\"><span style=\"font-weight: 400;\">high-traffic PHP applications<\/span><\/a><span style=\"font-weight: 400;\"> with read-heavy workloads, real-time APIs, and microservice backends.<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">composer require laravel\/octane<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">php artisan octane:install<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\"># Start with Swoole<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">php artisan octane:start &#8211;server=swoole &#8211;workers=4<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td><b>State Leakage \u2014 #1 Octane Gotcha<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Because the application stays resident in memory, static properties and singleton state persist between requests. A static variable set in Request A is still set in Request B. Audit your codebase for static state before running Octane in production \u2014 or use octane:install&#8217;s state-reset lifecycle hooks.<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<h3><b>10<\/b><\/h3>\n<\/td>\n<td>\n<h3><b>Performance Monitoring<\/b><\/h3>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">You cannot optimize what you cannot measure. Wire up monitoring before you start optimizing \u2014 not after.<\/span><\/p>\n<p><b>Flag slow queries in development<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400;\">DB::listen(function ($query) {<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 if ($query-&gt;time &gt; 100) { \/\/ Flag queries &gt; 100ms<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 \u00a0 \u00a0 logger()-&gt;warning(&#8216;Slow query&#8217;, [<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#8216;sql&#8217;\u00a0 =&gt; $query-&gt;sql,<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#8216;time&#8217; =&gt; $query-&gt;time,<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 \u00a0 \u00a0 ]);<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">\u00a0 \u00a0 }<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400;\">});<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><b>Recommended monitoring stack<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Laravel Telescope: <\/b><span style=\"font-weight: 400;\">Laravel Telescope \u2014 request lifecycle, query counts, queue jobs, cache hits in dev<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Laravel Debugbar: <\/b><span style=\"font-weight: 400;\">Debugbar \u2014 inline query profiling during development<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Blackfire: <\/b><span style=\"font-weight: 400;\">Production-safe profiler with call graph visualization<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>New Relic \/ Datadog APM: <\/b><span style=\"font-weight: 400;\">Distributed tracing, error rates, throughput dashboards<\/span><\/li>\n<\/ul>\n<h2><b>Quick Reference Summary<\/b><\/h2>\n<table>\n<tbody>\n<tr>\n<td><b>Technique<\/b><\/td>\n<td><b>Primary Benefit<\/b><\/td>\n<td><b>When to Apply<\/b><\/td>\n<\/tr>\n<tr>\n<td><b>Artisan optimize commands<\/b><\/td>\n<td><span style=\"font-weight: 400;\">Faster bootstrapping<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Every deployment<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>Eager loading (with\/withCount)<\/b><\/td>\n<td><span style=\"font-weight: 400;\">Eliminate N+1 queries<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Always with relationships<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>Selective columns<\/b><\/td>\n<td><span style=\"font-weight: 400;\">Less memory, faster I\/O<\/span><\/td>\n<td><span style=\"font-weight: 400;\">API responses, large tables<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>cursor() vs chunk()<\/b><\/td>\n<td><span style=\"font-weight: 400;\">Flat memory on large datasets<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Exports, batch jobs<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>Composite indexes<\/b><\/td>\n<td><span style=\"font-weight: 400;\">Filter + sort in one scan<\/span><\/td>\n<td><span style=\"font-weight: 400;\">High-read tables with WHERE + ORDER<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>Atomic cache locks<\/b><\/td>\n<td><span style=\"font-weight: 400;\">Prevent stampedes<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Cache miss under concurrent load<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>Redis<\/b><\/td>\n<td><span style=\"font-weight: 400;\">In-memory speed for all drivers<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Any production application<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>Queue workers + Horizon<\/b><\/td>\n<td><span style=\"font-weight: 400;\">Non-blocking request cycle<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Email, notifications, heavy jobs<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>PHP OPcache<\/b><\/td>\n<td><span style=\"font-weight: 400;\">Skip PHP compilation<\/span><\/td>\n<td><span style=\"font-weight: 400;\">Every production server<\/span><\/td>\n<\/tr>\n<tr>\n<td><b>Laravel Octane<\/b><\/td>\n<td><span style=\"font-weight: 400;\">In-memory app lifecycle<\/span><\/td>\n<td><span style=\"font-weight: 400;\">High-traffic APIs &amp; microservices<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2><b>Conclusion<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Laravel gives you the primitives for a fast application \u2014 but performance does not happen automatically. It requires deliberate decisions at every layer: query design, caching strategy, infrastructure configuration, and architectural patterns that scale. If your application is hitting performance limits or you are building a system that needs to handle significant scale, the <\/span><a href=\"https:\/\/www.icoderzsolutions.com\/hire-laravel-developers.shtml\"><span style=\"font-weight: 400;\">iCoderz Laravel team<\/span><\/a><span style=\"font-weight: 400;\"> has spent over a decade architecting and optimizing production systems across eCommerce, SaaS, and enterprise backends.<\/span><\/p>\n<table>\n<tbody>\n<tr>\n<td><b>Building or scaling a Laravel application?<\/b><\/p>\n<p><span style=\"font-weight: 400;\">iCoderz has delivered 650+ projects across SaaS, marketplaces, enterprise systems, and on-demand platforms. Our Laravel developers bring production-hardened experience to every engagement.<\/span><\/p>\n<p><a href=\"https:\/\/www.icoderzsolutions.com\/laravel-development.shtml\"><span style=\"font-weight: 400;\">Explore Laravel Development Services \u2192<\/span><\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2><b>Related Resources<\/b><\/h2>\n<p><a href=\"https:\/\/www.icoderzsolutions.com\/blog\/features-of-laravel\/\"><span style=\"font-weight: 400;\">10 Best Features of the Laravel PHP Framework<\/span><\/a><\/p>\n<p><a href=\"https:\/\/www.icoderzsolutions.com\/blog\/laravel-13-is-released\/\"><span style=\"font-weight: 400;\">Laravel 13 Is Released \u2014 What&#8217;s New<\/span><\/a><\/p>\n<p><a href=\"https:\/\/www.icoderzsolutions.com\/blog\/laravel-for-e-commerce-website\/\"><span style=\"font-weight: 400;\">How to Build an E-Commerce Website in Laravel<\/span><\/a><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Laravel is one of the most widely used PHP frameworks for building modern web applications. As applications grow, performance gaps compound. Slow queries, untuned caches,&#8230;<\/p>\n","protected":false},"author":21,"featured_media":12202,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1203,298],"tags":[424,1235,2015],"class_list":["post-7234","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-laravel","category-web-development","tag-laravel","tag-laravel-performance","tag-laravel-performance-optimization"],"_links":{"self":[{"href":"https:\/\/www.icoderzsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/7234","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.icoderzsolutions.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.icoderzsolutions.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.icoderzsolutions.com\/blog\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.icoderzsolutions.com\/blog\/wp-json\/wp\/v2\/comments?post=7234"}],"version-history":[{"count":0,"href":"https:\/\/www.icoderzsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/7234\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.icoderzsolutions.com\/blog\/wp-json\/wp\/v2\/media\/12202"}],"wp:attachment":[{"href":"https:\/\/www.icoderzsolutions.com\/blog\/wp-json\/wp\/v2\/media?parent=7234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.icoderzsolutions.com\/blog\/wp-json\/wp\/v2\/categories?post=7234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.icoderzsolutions.com\/blog\/wp-json\/wp\/v2\/tags?post=7234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}