Optimizing Laravel Performance: Caching Strategies for a Speedy Application

Posted on April 8th, 2024

Laravel is a popular framework for developers to develop dynamic and feature-rich business applications as well as e-commerce websites. As we develop a Laravel application time by time,  we can face multiple database queries and requests. It directly affects your Server and CPU performance. You may increase server capacity to improve website performance.

But thanks to Laravel for providing a caching system for optimizing an application and better performance.

The question is, why do we use a caching system in Laravel? The answer is to :

  • Enhanced User Experience: it is proven that faster load time keeps users engaged. The Research found that 1 second of load lag time would cost Amazon around $1.5 billion in sales per year.

  • Improve SEO Ranking: Search engines like Google prioritize fast-loading websites in search results.
  • Increased Scalability: As your user base grows, your application needs to handle the additional traffic. Caching helps ensure your Laravel app scales efficiently.

Caching in Laravel

In simple terms, caching is all about storing a piece of data in temporary storage, whether it’s database queries, rendered views, or even entire web pages.

In Laravel, caching is a hand-on feature to increase your application’s response time.

How does caching actually work in Laravel? Well, Laravel provides a clean and intuitive API for working with caches, making it easy to store and retrieve cached data using a variety of drivers, including database, file, Redis, Memcached, and more.

Types of caching in Laravel

Let’s talk about different types of caching strategies that can help you empower different specific areas to optimize performance.

1. Route Caching

Route caching stores information about routes in your application, reducing repetition calls and significantly improving performance for frequently accessed routes.

Let’s understand with an example.

Suppose you have a controller called HomeController.php in which you define an index method like the following.

// app/Http/Controllers/HomeController.php
public function index()
{
return view('welcome');
}

In the above code, the index method is a frequently accessed route. By enabling route caching, Laravel can store the route information for this method, avoiding the need to access it on every request.

Here’s how to enable route caching in your config/cache.php file:

'cache' => [
'default' => env('CACHE_DRIVER', 'file'),
'stores' => [
'file' => [
'driver' => 'file',
'path' => storage_path('framework/cache'),
],
// ... other cache store configurations
],
'enable' => [
'routes' => true,
// ... other cache options
],
];

In the above code, we set route => true under the enable key. What we do is instruct Laravel to cache route information. This can significantly improve performance for commonly accessed routes, especially on larger applications.

2. View caching

Blade template is the fundamentals of Laravel view. By using Blade in Laravel, you can efficiently structure your application. But parsing templates on every request is like overhead.

And that’s why we need to use View Caching. It stores compiled versions of blade templates and significantly reduces rendering time.

Here is an example of how you can use View Caching in Laravel:

// resources/views/welcome.blade.php
<h1>Welcome to our Laravel Application!</h1>
<p>This is the content of our home page.</p>

Above is the simple welcome page blade template called welcome.blade.php. Every time users call this template, Laravel needs to parse the template. Here, you can use view caching to store the compiled version of your template, eliminating the parsing step and resulting in much faster rendering.

Here’s how to enable view caching in your config/cache.php file:

'cache' => [
'default' => env('CACHE_DRIVER', 'file'),
'stores' => [
'file' => [
'driver' => 'file',
'path' => storage_path('framework/cache/views'),
],
// ... other cache store configurations
],
'enable' => [
'views' => true,
// ... other cache options
],
];

In the above code, we do the same as the route caching. Just set up views => true under the enable key. By doing this, when users call the template, it checks the cache for the pre-compiled version. If it exists, it will be used directly, resulting in a significant performance boost.

3. Object Caching or Query Caching

As we already know, database queries can be essential for accessing data in your Laravel application. But frequent queries at a time lead to increased database server load.

Object caching or query caching tackles this by storing the results of database queries or complex objects in a temporary location, reducing the need for repeated database interactions and improving response times.

Here is an understandable example:

// app/Http/Controllers/PostController.php
public function show(Post $post)
{
return view('posts.show', compact('post'));
}

In the above code, the show method retrieves the specific post from the database. Querying this post in every request can be insufficient. Object caching allows you to store retrieved post objects in the cache for a specific duration of time. As a result, Laravel retrieves the data from the cache instead of hitting a query each time.

Here is how you can use an object caching system to cache the post object.

public function show(Post $post)
{
$cachedPost = Cache::remember(
'post:' . $post->id,
60, // Cache for 60 minutes
function () use ($post) {
return Post::find($post->id);
}
);

return view('posts.show', compact('cachedPost'));
}

In the above code, we use Cache::remember method, and it takes three arguments which is:

  1. Cache Key: A unique identifier for the cached data (‘post:’ . $post->id).
  2. Duration: The amount of time to keep the data in the cache. Here, we set 60 min.
  3. Closure: A function that retrieves the data if it’s not found in the cache.

It is recommended to use object caching to reduce database load and increase application response time significantly.

4. Fragment Caching

Fragment caching can allow you to cache individual sections of a blade template, providing more flexibility in what gets stored and retrieved from the cache.

Here is an example of fragment caching.

Imagine you can have multiple categories on your news website. Let’s say “breaking news” and “sports”. Fragment caching lets you cache just the breaking news section, while the sports section can remain dynamic and update frequently.

// resources/views/welcome.blade.php
<div id=”breaking-news”>
@cache(‘breaking-news’, 30) @endcache
</div>
<div id=”sports-headlines”>
</div>

In the above example, we use the @cache directive to cache the content within the breaking-news section. It takes the following two arguments.

  1. Cache Key: A unique identifier – breaking-news
  2. Cache Duration: The amount of time to take the fragment in the cache. Here, we use 30 sec.

When any user requests the welcome page, it first checks the cache for the breaking-news fragment. If it exists, it will be used directly. Otherwise, the content will be rendered and stored in the cache for future requests.

In short, fragment caching gives you flexibility to use caching, allowing you to optimize specific parts of your views while keeping other sections dynamic.

5. Page Caching

Page Caching is used for content that rarely changes, like product descriptions or static pages. Page caching can significantly reduce server load.

Here is a simple example of page caching.

// app/Http/Controllers/ProductController.php
public function show(Product $product)
{
if (Cache::has('product:' . $product->id)) {
return Cache::get('product:' . $product->id);
}

$view = view('products.show', compact('product'));
Cache::put('product:' . $product->id, $view->render(), 60 * 24); // Cache for 24 hours

return $view;
}

In this example, we’re checking if the pre-rendered HTML for the product page exists in the cache. If it does, we can directly return it, saving processing time. Otherwise, we render the view using Blade and store the entire HTML output in the cache for 24 hours.

Note that page caching is ideal only for content that updates infrequently. 

Choosing the Right Cache Backend for Laravel

Laravel provides a variety of cache backends based on different needs. Let’s discuss the most common ones.

  1. File System: The default cache driver uses the local file system to store cached data. It’s a simple and easy-to-use option and ideal for low-traffic applications.
  2. Database: This driver stores cached data in your database tables.
  3. Memcached: This is an in-memory caching system known for its speed and scalability. It stores data in RAM, making retrieval significantly faster compared to disk-based options like the File System.
  4. Redis: Redis offers a broader feature set compared to Memcached. It supports various data structures like lists, sets, and hashes, making it suitable for more complex caching scenarios.

By using the above caching strategies, you can transform your Laravel application into a high-performance machine that keeps your users happy and engaged.

For more information about caching, you can follow the Official Laravel Document. With that you can also follow Laravel Caching Tutorial for a step-by-step guide about caching.

Leave a Reply