• Insights

Output caching in Kentico

Senior Developer Lee discusses the controversy of caching, and how best to use it

Caching can be a sensitive subject in some circles of development. In my experience, a respectable number of developers are in one of two camps when it comes to caching:

  • Cache everything, to death, without exception
  • Never use caching: caching is evil

The “cache everything” camp claim that caching improves performance of websites and applications by reducing the amount of processing the server must do.

The “caching is evil” camp claim that caching is used far too often as a crutch to cover up performance issues in badly written code.

The reality, as always, is somewhere in the middle. I believe that caching has its place but should be used intelligently and be appropriate to the application and use-cases it is covering.

Kentico carries out a lot of caching right out of the box but much of that is in the data access layer and the caching is that of SQL query results to avoid hitting the database on every page request.

What I’d like to talk about today is output caching in Kentico.

What is output caching?

Output caching, at its most basic, is the act of caching the result of a given request, and then serving that same result over and over again until the cache expires.

Typically, web applications will cache the output based on certain parameters. For example, it would be silly to cache the mobile version of a page for desktop browsers – so the web server will often create different cache versions based on the browser making the request (i.e. user-agent).

When should I use it?

I believe that output caching should be used on any production website. It doesn’t matter how fast your site performs without it, it will perform faster with it.

The key points to consider are:

  • How long should I cache for?
  • Under what criteria should cache be invalidated?

Ultimately you will need to decide these things for yourself based on the site or application you are developing.

For example, if your site only gets 1 visitor per hour on average it would be of no use to have a 30-minute cache time since no one would ever hit the cache.

Check the analytics history of the site and select a sensible time.

How do I use it?

To turn on Output Caching in Kentico go to Settings > System > Performance and check the box “Enable output caching”.

Configure the other options in this section to your requirements.

Note: If you use alias paths to carry out redirects or you have redirects to switch from HTTP to HTTPS, you will want to add “domain” to this list of output cache variables as Kentico considers the protocol part of the domain for the purposes of output caching.

In order to ensure that pages show the correct output and clear their caches when needed you should evaluate each page of the site and place the “Output cache dependencies” web part on pages where you need to expire the cache based on changes to other objects or pages.

For example, if you have a blog listing page (/blog) that displays a repeater of blog posts (which are children of /blog) then you will need to set the blog posts as cache dependencies of the blog listing page.

On your blog listing page add the Output Cache Dependencies web part and set a dependency as follows:

node|<yoursitecodename>|/blog|childnodes

The dependency above allows any changes to any of the blog posts that are children of /blog to invalidate the output cache of the /blog page.

The Output Cache Dependencies web part uses the same dependencies as you might use in data sources and repeaters. You can find full details in the Kentico documentation.

Using Cache Substitutions

Substitutions are like macro expressions in their usage on the site. Instead of {% … %} you would use {~ … ~}. The main difference is that there is no logic in a substitution expression. Substitutions are simply a placeholder or marker for a location that you wish to render some content that is never cached in the output cache.

You can read more about how to create substitutions in the Kentico documentation.

A good example of where to use such a substitution would be on an ecommerce site where you want to show the current value of the shopping cart in the header of each page. With output caching enabled this value would not update when items are added or removed from the cart.

A simple substitution can be used to ensure that it is always updated.

Here’s the static method I use:

public static void ResolveCustomSubstitutions(object sender, SubstitutionEventArgs e)
{
     // Checks that the substitution expression is not resolved yet
    if (!e.Match)
    {
        // Branches according to the expression text of the substitution macro
        // You can define any number of substitution macros by adding further cases
        switch (e.Expression.ToLower())
        {
            // Handles the {~cartitemscount~} substitution macro
            case "cartitemscount":
	 
            // Flags the substitution expression as resolved
            e.Match = true;
	 
            // Returns the current number of items in the shopping cart as the result of the substitution
            e.Result = ECommerceContext.CurrentShoppingCart.TotalUnits.ToString();
            break;
        }
    }
}

Then it just must be registered in a module initialisation:

ResponseOutputFilter.OnResolveSubstitution += MyStaticClass.ResolveCustomSubstitutions;

Once you have this in place, you can use a Static HTML or Static Text web part and simply place the expression somewhere within the output of the web part as follows:

{~cartitemscount~}

This will then output the total items in the shopping cart (in this example) without that output being caught in the output cache and displayed to every visitor. You could use similar substitutions to display the users name in the header of your page for example, while still benefiting from output caching for the rest of the page.

Final Thoughts

In summary, Kentico output caching can take your site from fast to blazingly fast when used correctly. Just make sure that you understand the potential pitfalls, and avoid using output caching (or caching of any kind) as a crutch to hide poor performance.

Did you find this article helpful? Got any comments or questions? Let us know in the comments below, and feel free to like and share!

Author:Lee Conlin

More insights