Laravel is the most popular PHP framework for building web applications and is loved for its elegance, simplicity, and scalability. However, like any other framework for web development, Laravel can experience performance issues if it’s not optimized for high performance. Laravel performance problems aren't usually due to the framework itself, but rather some suboptimal choices in the application. In this article, we’ll explore some best practices for optimizing Laravel applications for high performance.

Why should I bother with optimization?

  1. Improved performance: Optimization can significantly improve the speed and performance of your Laravel application. Faster response times, quicker page load times, and reduced server load can all lead to a better user experience and higher user engagement.
  2. Better user experience: Faster load times and reduced page load times can improve the user experience of your application. Users are more likely to continue using an application that loads quickly and smoothly than a slow and unresponsive application. Learning how to improve Laravel performance pays dividends over time for your users.
  3. Cost savings: Optimizing your Laravel application can save your business money by reducing server load, which can lower hosting costs. It can also reduce the amount of time and effort required to maintain your application.
  4. Scalability: Focusing on Laravel performance optimization for your application can make it more scalable, allowing it to handle more traffic and users without compromising performance. This is particularly important if you expect your application to grow over time.
  5. Security: Optimization can also serve a dual purpose, improving the security of your Laravel application by reducing the risk of vulnerabilities and attacks.

Overall, Laravel performance optimization can lead to a better user experience, improved performance, and cost savings, making it an important consideration for any web developer or business owner.

How to measure Laravel performance for your app

Measuring your Laravel app’s performance is important to ensure that your application is running efficiently and delivering the best possible user experience. Here are some ways to measure your app’s performance:

Code profiling

Code profiling, one option for Laravel performance monitoring, involves measuring the performance of your code by analyzing the execution time and memory usage of specific functions or methods. You can use a tool like Xdebug or Blackfire to perform code profiling on your Laravel application. To use Blackfire, ensure that your environment meets the following requirements:

  • PHP version 7.3 or higher
  • illuminate/console version 8.0 or higher
  • illuminate/support version 8.0 or higher

Blackfire homepage, a tool that helps you optimize Laravel performance Blackfire

Then, install the Blackfire PHP SDK using Composer:

composer require blackfire/php-sdk

Register the Blackfire\Bridge\Laravel\ObservableCommandProvider service provider in the config/app.php file:


'providers' => [
    // Other service providers
    Blackfire\Bridge\Laravel\ObservableCommandProvider::class,
],

Start the Blackfire agent and enable the Blackfire probe in your PHP environment:

  • If you are using Blackfire.io, follow the instructions in your Blackfire account to configure the agent and enable the probe.
  • If you are using Blackfire Player or Blackfire Player Cloud, follow the instructions in the Blackfire Player documentation to configure the agent and enable the probe.

Run your Laravel Artisan command with the --blackfire option to profile the command:

php artisan my:command --blackfire

The Blackfire probe will automatically start and stop profiling during the execution of the command. Once the command has finished executing, the profiling results will be sent to your Blackfire account or displayed in your console, depending on your configuration.

Laravel also comes with a built-in profiler called Telescope that allows you to monitor various aspects of your app's performance, including DB queries, HTTP requests, and exceptions. You can use Telescope to identify slow queries or other performance issues.

Telescope, Laravel's built-in profiler that helps to monitor your website performance Telescope

Logging

Laravel's logging feature can help you track errors and exceptions that occur in your application. By reviewing the logs, you can identify bottlenecks or performance issues that need to be addressed.

Benchmarking

Benchmarking is the process of testing the performance of your application under a specific workload or set of conditions. You can use tools like Apache Bench or Siege to simulate load on your application and measure how it performs to improve Laravel performance.

Caching

Caching is a quick way to make Laravel faster since Laravel has a robust caching system that can help improve performance by storing frequently accessed data in memory. By monitoring cache hits and misses, you can determine if your caching strategy is effective.

Database profiling

Laravel provides several tools to monitor and optimize database performance, including the query builder and Eloquent ORM. You can use these tools to identify slow queries and optimize database access.

By using these techniques, you can gain insight into the performance of your Laravel application and identify areas for improvement. Now let’s get into methods for optimizing Laravel applications.

Caching data

Caching is the process of storing frequently accessed data in a quick-to-retrieve location like memory so that it can be retrieved quickly, without having to query the database every time. Caching is often used for Laravel performance tuning because Laravel provides several caching drivers such as File, Database, Memcached, Redis, and APCu.

Choose the right caching driver

Choosing the right caching driver is essential, as it can impact your application's performance. For instance, if you have a large amount of data to be cached, Memcached or Redis is the best option because they are in-memory caching systems that can handle large amounts of data. For small applications, File or Database caching drivers are also good options.

Set up caching in Laravel

Once you have chosen the most appropriate caching driver, the next step is to set up caching in Laravel. Laravel provides a caching configuration file, which you can find in the config/cache.php directory. You can set the default cache driver in the config/cache.php file, and you can also set different caching drivers for specific areas of your application.

Caching database queries

One of the best ways to improve your application's performance is by caching database queries. Database queries are slow when compared to puling values out of memory. Laravel provides a simple way to cache database queries using the cache() method. Here's an example:

$users = cache()->remember('users', $minutes, function () {
    return DB::table('users')->get();
});

In the above example, the remember method is used to cache the database query results for a specified number of minutes. If the data are already cached, Laravel will retrieve the cached data instead of running the query again.

Caching views

You can also cache views in Laravel to improve your application's performance. When you cache a view, Laravel will store the rendered HTML in the cache so that it can be retrieved quickly. To cache a view in Laravel, you can use the cache() method in your controller or view file. Here's an example:

Route::get('/', function () {
    $data = ['name' => 'John Doe'];
    $content = cache()->remember('home', $minutes, function () use ($data) {
        return view('home', $data)->render();
    });
    return $content;
});

In the above example, the home view is cached for a specified number of minutes using the remember method. If the data is already cached, Laravel will retrieve the cached HTML instead of rendering the view again.

Clearing the cache

It's important to clear the cache when necessary. Laravel provides an artisan command for this purpose:

php artisan cache:clear

You can also clear the cache for a specific driver using the cache:clear command:

php artisan cache:clear redis

Use route caching

Using route caching can significantly improve application boot-times by reducing the number of route files that need to be loaded. To cache routes, run the following command in your terminal:

php artisan route:cache

This will generate a cached file of your application’s routes that can be loaded faster.

Use config caching

Caching configuration files can also improve application boot-times. To cache configuration files, run the following command in your terminal: It's important to clear the cache when necessary. Laravel provides an artisan command to clear the cache:

php artisan config:cache

This will generate a cached file of your application’s configuration that can be loaded faster.

Use OpCache

OpCache is a PHP extension that caches compiled PHP code in memory, reducing the time it takes to load PHP files. To enable OpCache, add the following lines to your PHP configuration file:

opcache.enable=1
opcache.enable_cli=1

Using caching in Laravel can often result in a significant Laravel performance optimization. By caching frequently accessed data, you can reduce the number of database queries an application needs to make and improve page load times.

Optimize autoloading

Laravel’s Composer-based autoloading can slow down application boot-times, especially in large applications. You can optimize autoloading by using Composer’s classmap option, which generates a static map of class files to load. To generate a classmap, run the following command in your terminal:

composer dump-autoload --optimize --classmap-authoritative

This will generate an optimized classmap that loads classes faster.

Use queues

Laravel queues can be a powerful tool for Laravel performance optimization as well as scalability improvements. Queues allow you to defer time-consuming tasks, such as sending emails or processing large datasets, to background workers. This frees up your application to handle other requests and ensures that your users have a fast and responsive experience. Let's walk through the steps necessary to start using queues in Laravel.

Set up a queue driver

To use queues in Laravel, you'll first need to set up a queue driver. Laravel supports several queue drivers out of the box, including Beanstalkd, Redis, and Amazon SQS. The specific driver you choose will depend on your application's needs and your hosting environment. To set up a queue driver, you'll need to configure the driver's settings in your application's .env file or in the config/queue.php file. Here's an example configuration for the Beanstalkd driver:

QUEUE_CONNECTION=beanstalkd
QUEUE_HOST=127.0.0.1
QUEUE_PORT=11300

Define jobs

Next, you'll need to define the jobs that you want to add to the queue. Jobs are simple classes that encapsulate a specific task that needs to be performed. For example, you might create a job that sends an email or a job that processes a large data set. Here's an example job that sends an email:

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
use App\Mail\WelcomeEmail;

class SendWelcomeEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $user;

    public function __construct($user)
    {
        $this->user = $user;
    }

    public function handle()
    {
        Mail::to($this->user->email)->send(new WelcomeEmail($this->user));
    }
}

Dispatch jobs

Once you've defined your jobs, you can easily dispatch them to the queue using Laravel's queue API. To dispatch a job, simply call the dispatch() method on the job class. Here's an example:

use App\Jobs\SendWelcomeEmail;

$user = App\User::find(1);

SendWelcomeEmail::dispatch($user);

Run workers

Finally, you'll need to run the queue workers that will process the jobs. Laravel provides a simple command-line interface for running queue workers. To start a worker, run the following command:

php artisan queue:work

This will start a worker that will listen for incoming jobs on the default queue connection. If you're using a different queue connection, you can specify it with the --queue option:

php artisan queue:work --queue=beanstalkd

By default, workers will process one job at a time. If you want to process multiple jobs in parallel, you can specify the --workers option:

php artisan queue:work --workers=4

Using queues can be a powerful way to improve the performance and scalability of your Laravel application. By deferring time-consuming tasks to background workers, you can ensure that your application remains fast and responsive, even under heavy loads.

Optimize database queries

Optimizing database queries is a common way developers optimize Laravel application performance. You can speed up database queries by using Laravel’s Query Builder or Eloquent ORM to write efficient queries that retrieve only the necessary data. Here’s an example of optimizing a database query using Eloquent:

// Inefficient query
$users = User::all();

// Efficient query
$users = User::select('id', 'name')->get();

The efficient query only retrieves the id and name columns, reducing the amount of data that needs to be retrieved.

Optimize images

Images can also be a significant bottleneck in Laravel applications. Large image files can take a long time to load, which can slow down the application. You can optimize images by compressing them, resizing them, and using a content delivery network (CDN) to deliver them faster. This is often easier than actual changes to an application, so evaluating image sizes is a great place to start when seeking to improve application performance.

Use CDNs

CDNs can significantly improve the performance of Laravel applications by delivering static resources, such as images, stylesheets, and JavaScript files, from servers located closer to the user. This can reduce the time it takes to load resources, improving the user experience. Laravel’s integration with CDNs is seamless, and you can use various CDNs, including Cloudflare, Amazon CloudFront, and Akamai.

Minimize HTTP requests

Minimizing HTTP requests is a critical aspect of optimizing your Laravel application for high performance. Each time a user loads a webpage, the browser sends a request to the server for each resource required to display the page, including HTML, CSS, JavaScript, images, and other media. Each HTTP request creates a round-trip delay, which can slow page load times and impact user experience.

To minimize HTTP requests, you can take the following steps:

Combine CSS and JavaScript files.

Combining CSS and JavaScript files into a single file can reduce the number of HTTP requests required to load a web page. By reducing the number of requests, you can improve page load times and provide a better user experience. You can use Laravel Mix to combine and minify your CSS and JavaScript files.

Use image sprites.

Using image sprites is another way to minimize HTTP requests. Image sprites combine multiple images into a single image file, reducing the number of requests required to load the images. By using CSS to display specific portions of the sprite, you can display individual images while minimizing HTTP requests. You can use a tool like Spritesmith to generate image sprites for your Laravel application.

Lazy and eager loading

In Laravel, loading related models can be done using either eager loading or lazy loading. Eager loading is the process of loading related models at the same time as the parent model. This is achieved using the with() method, which preloads the related models for all parent models in a single database query. Eager loading can improve the performance of your application by reducing the number of database queries needed to fetch related models. It's especially useful when you need to fetch related models for multiple parent models at the same time. Here's an example of using eager loading in Laravel:


// Eager load the posts relationship for all User models
$users = User::with('posts')->get();

foreach ($users as $user) {
    // Access the posts relationship without additional database queries
    $posts = $user->posts;
}

In this example, the with() method is used to preload the posts relationship for all User models in a single database query. The related posts models are eagerly loaded when the User models are fetched, which means that accessing the posts relationship does not require additional database queries.

Lazy loading, however, is the process of loading related models only when they are explicitly requested. The related models are only loaded when the proxy object is accessed. Lazy loading can improve the performance of your application by reducing the memory usage and database load of your application. It's especially useful when you don't need to fetch related models for all parent models at the same time. Here's an example of using lazy loading in Laravel:


// Lazy load the posts relationship for a single User model
$user = User::find(1);

// Access the posts relationship, which triggers a database query
$posts = $user->posts;

In this example, the posts relationship is lazily loaded only when it's accessed. The related posts models are also not loaded until the posts relationship is accessed, which means that accessing the posts relationship requires a database query.

Optimizing for high performance

Optimizing Laravel applications for high performance requires a comprehensive approach that covers all aspects of the application, from caching and database queries to image optimization and CDN usage. By following the best practices outlined in this article, you can improve the Laravel performance for your application and provide a better user experience for your users.

It’s important to note that Laravel performance optimization is an ongoing process. As your application grows, you may need to revisit your optimization strategy and make changes accordingly. Regular performance testing can help you identify performance bottlenecks and fine-tune your optimization strategy for maximum efficiency.

Finally, it’s worth noting that optimizing your Laravel application for high performance requires a balance between performance and maintainability. While optimizing for performance is important, it’s equally important to ensure that your application remains maintainable and easy to work with over the long term. By striking a balance between performance and maintainability, you can create a high-performance Laravel application that’s both efficient and sustainable.

Get the Honeybadger newsletter

Each month we share news, best practices, and stories from the DevOps & monitoring community—exclusively for developers like you.
    An advertisement for Honeybadger that reads 'Turn your logs into events.'

    "Splunk-like querying without having to sell my kidneys? nice"

    That’s a direct quote from someone who just saw Honeybadger Insights. It’s a bit like Papertrail or DataDog—but with just the good parts and a reasonable price tag.

    Best of all, Insights logging is available on our free tier as part of a comprehensive monitoring suite including error tracking, uptime monitoring, status pages, and more.

    Start logging for FREE
    Simple 5-minute setup — No credit card required