the-editor 3 years ago

Ultimate Laravel Performance Optimization

Laravel is pretty fast out-of-the-box, but you can make it faster if you optimize your configurations and application code.

This guide lists a wide range of performance tips from quick wins to advanced techniques that would help you make your Laravel app the lean, mean machine your customers want.


Performance

We can all agree that we prefer an app that loads faster to one that's slow. According to a Google study, 53% of mobile users leave a site that takes longer than 3 seconds to load.


Every second your app takes longer to load, you're probably losing customer conversions. Thankfully, for Laravel apps, it's not a very difficult problem to solve.


1. Use In-Built Performance Quick Wins

Laravel offers a few in-built performance quick wins that can apply to any app.

The most significant performance quick win is route caching.


Did you know that every time you boot your Laravel app, your app determines the middleware, resolves aliases, resolves route groups, and identifies the controller action and parameter inputs for every single route entry?


You can bypass the route processing by caching all the required routing information using the route:cache Artisan command:

php artisan route:cache

This command can give you up to a 5x performance boost! It can make a significant impact on your app performance.


Routes caching is an essential optimization feature, particularly for apps with a lot of routes and configurations. The routes cache is a simple array and helps in speeding up Laravel performance because of the faster loading of the array.


Besides route caching, Laravel also offers the following:

Configuration caching to bypass parsing your .env and config files on every app boot:

php artisan config:cache


View caching to pre-compile your Blade template views:

php artisan view:cache


Event caching to cache a manifest of all of your app's events and listeners:

php artisan event:cache


You should make sure to add the above caching commands to your deployment script so that every time you deploy, your routes, config, views, and events are re-cached. Otherwise, any changes you make to your route or config files will not update in your application.


Remember to run the command every time config or the routes files have been changed, otherwise, Laravel will load old changes and from the cache. For clearing the cache, use the following command:

php artisan route:clear


2. Optimize Composer

A common mistake sometimes made by Laravel developers is to install all dependencies in production. Some development packages such as Ignition record your queries, logs, and dumps in memory to give you a friendly error message with context for ease of debugging.


While this is useful in development, it can slow down your application in production. In your deployment script, make sure to use the --no-dev flag while installing packages using Composer:


composer install --prefer-dist --no-dev -o


Additionally, make sure to use the `-o' flag in production as above.

This enables Composer to optimize the autoloader by generating a "classmap".


You may choose to use the --classmap-authoritative flag instead of the `-o' flag for further optimization if your app does not generate classes at runtime. Make sure to check out the Composer documentation on autoloader optimization strategies.


3. Choose The Right Drivers

Choosing the right cache, queue, and session drivers can make quite a difference to application performance.


For caching in production, we recommend the in-memory cache drivers such as Redis, Memcached, or DynamoDB. You may consider local filesystem caching for a single-server setup, although it would be slower than the in-memory options.


For queueing, we recommend the Redis, SQS, or Beanstalkd drivers.

The database driver is not suitable for production environments and is known to have deadlock issues.


For sessions, we recommend the Database, Redis, Memcached, or DynamoDB drivers.

The cookie driver has filesize and security limitations and is not recommended for production.


4. Queue Your Time-Consuming Tasks

There may be specific tasks that take a long time to perform during a typical web request. Laravel has a best-in-class queueing system that allows us to move time-consuming tasks to queued jobs so that your application can respond to requests with blazing speed.


Common examples of such tasks are parsing and storing a CSV file, interacting with third-party APIs, sending notifications to users, expensive database queries, and updating your search index.


5. Set Compression Headers on Text Format Files

Compression headers can have a significant impact on application performance. Ensure that you enable compression headers on your web server or CDN for text format files, like CSS, JS, XML, or JSON.


Most image formats are already compressed and are not text format files (with the exception of SVG, which is an XML document). So, image formats do not need to be compressed.


You may set up gzip or brotli (preferably both as brotli may not be supported for older browsers) at your web server or CDN level to achieve a huge performance boost.


Typically, compression would be able to reduce your file size by around 80%!


6. Set Cache Headers on Static Assets

Caching can provide a performance boost for your application, especially for static assets such as images, CSS, and JS files. It is recommended to enable cache-control headers at the webserver level or at your CDN level (if applicable). If you wish to set these headers at your Laravel app instead of the webserver, you may use Laravel's cache control middleware.


Cache headers ensure that browsers don't request static assets on subsequent visits to your website. This can enhance your user experience as your website loads faster on subsequent visits.


Make sure you use cache-busting so that when you change your CSS or JS code, browsers avoid relying on stale cached content. Laravel Mix provides cache busting out of the box.


7. Consider Using a CDN to Serve Assets

Content Delivery Networks (CDNs) are a geographically distributed group of servers that serve content closer to application visitors by using a nearby server. This enables visitors to experience faster loading times.


Besides faster loading times, CDNs also have other benefits such as decreased web server load, DDoS protection, and analytics on assets served. Some popular CDNs include Cloudflare, AWS Cloudfront, and Azure CDN. 


8. Minify your JS and CSS Code

Minification strips extra code from your application that is not essential for execution (like comments, whitespace, renaming variables with shorter names, and other optimizations). It's always a good idea to minify JS and CSS files in production.


9. Remove Unused Services

In the context of Laravel performance tuning, an important tip is not to load all services through the config. While you are there, always remember to disable unused services in the config files. Add comments to these service providers.


10. Classmap Optimization

Even a mid-level Laravel app has a number of files because Laravel has the habit of calling including multiple files for include requests. A simple trick is to declare all the files that would be included to include requests and combine them in a single file. Thus, for all include requests, a single file will be called and loaded.

For this, use the following command:

php artisan optimize --force


11. Limit Included Libraries

The good thing about Laravel is the huge number of libraries that could be included in an app. While this is a good thing, the downside is the high level of drag that the application experiences and the overall experience slow down.


This is why it is important to review all the libraries’  recalled within the code. If you think you could do without a library, remove it from the config/app.php to speed up the Laravel app.

And take a good look at your composer.json....


12. Choose a Fast Cache and Session driver

The driver key for changing the session driver is usually located in app/config/session.php. Likewise, the driver key for changing the cache driver is located in app/config/cache.php


Checking the handle method of the StartSession middleware you can see that, when using the 'cookie' driver for the session storage, the data is written to the storage ( the cookie ) BEFORE the response is sent to the browser.


However, when using, for example, 'file' or 'database' session driver, the data is written to the storage AFTER the response has been sent to the browser, in the terminate method.


That happens probably for performance reasons: the primary concern of the app is to send the response to the client as soon as possible. If we're using the cookie driver, Laravel is someway 'forced' to store the data to the storage before sending the response, as the session info is needed to be stored in the cookie that is sent with the response. While, in the other cases, laravel can delay the writing to the storage, sending the response as soon as possible.


13. Cache Queries Results

Caching the results of the queries that are frequently run is a great way of improving Laravel performance.

For this, I recommend the remember function, that is used as follows:


$posts = Cache::remember('index.posts', 30, function()

{return Post::with('comments', 'tags', 'author', 'seo')->whereHidden(0)->get();});


14. Use “Eager Loading” for Data

Laravel offers a great ORM for dealing with databases. Known as Eloquent, it creates models that abstract the database tables from the developers. Using simple structures, developers could use Eloquent to deal with all CRUD operations in PHP. When Eloquent uses eager loading, it retrieves all associated object models in response to the initial query. This adds to the response of the application. Let’s compare lazy loading and eager loading:


The lazy loadijg nquery will look like:

$books = App\Book::all();

foreach ($books as $book) {echo $book->author->name;}


In contrast, the eager loading query will look like:

$books = App\Book::with('author')->get();

foreach ($books as $book) {echo $book->author->name;}


15. Running the latest version of PHP

The latest version of PHP has brought significant improvements in its performance. Therefore ensure that your Laravel application is running the latest version of PHP so that you can tap all the performance improvements introduced in the new version in your application.


Currently Supported Versions

Vers. - Release - Active Support - Security Support

7.3  -  06 Dec 2018 - 06 Dec 2020 - 06 Dec 2021

7.4  -  28 Nov 2019 - 28 Nov 2021 - 28 Nov 2022

8.0  -  26 Nov 2020 - 26 Nov 2022 - 26 Nov 2023


16. Laravel Debugbar

Though not an optimization technique, but a package. Laravel Debugbar is a package to integrate PHP Debug Bar with Laravel. It includes a ServiceProvider to register the debugbar and attach it to the output.

It is a package that can be used as a Laravel performance monitor.

It is recommended to make use of this package while developing your application.

Because with it, you can easily inspect how your application is running, and then improve accordingly.

https://github.com/barryvdh/laravel-debugbar


Q: How many requests can Laravel handle?

Without Sessions: 609.03 requests per second

With Sessions: 521.64 requests per second


Conclusion

Laravel performance tuning and optimization is an essential concern for all businesses that rely upon Laravel powered tools for business processes. Performance is a wide topic, but Laravel has several components built-in such as Mix, queues, and caching that make performance look easy! We hope that you learned something new about boosting your app's performance.