eZ Community » Learn » eZ Publish » eZ Publish Cache In Details:...

eZ Publish Cache In Details: Template-block Cache

Thursday 02 May 2013 8:56:14 am

  • Currently 3 out of 5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Impact in the choice of cache-block parameters

As the official documentations explains, it is possible to configure its “cache-blocks” using various parameters. Each of these parameters can have huge effects on the performance of a website. In other words, the most common performance problems are related to the misuse of « cache-blocks » or a misunderstanding of the way they work and the impact of a particular setting tweak.

Before describing in detail each setting and its impact, it is important to consider that :

  • If the homepage generates SQL queries (> 0 for the hompage, > 1 for internal pages), some « cache-block » are clearly missing somewhere
  • If we include a « cache-block » without understanding the meaning and the impact (by a simple copy and past for example), we are losing control of the performances 

 The « keys » parameter

As the documentation explains, we are talking here about defining an unicity key of the « cache-block ». That is to say that every time the key will be « identical », the same cache will be included in the execution of the template. The opposite conclusion is true as well, every time the key will be « different » (a new key that did not exist previously), the template (compiled or not) will be executed and cached.

One can infer from this behavior some critical situations, for example on a key of the type:

{cache-block keys=$module_result.uri}

This directive implies that we will cache as many « xHTML » as there is invokable URLs on the website. In a modern Web, populated with pagination, facets filters, indexing robots and other infinite URLs vacuums, the potential number of produced cache (and cache to be reproduced after each expiry) is relatively complex, however a rough simulation allows us to deduce that this directive should never be written on a high traffic website:

  • Let’s take a lambda website: a website of about 1000 pages + a list of 200 news with pagination, topic filters, a calendar, etc.
  • Let’s simulate every possible combinations of URLs: list of pages PLUS the pages offering variants for combined filters, paginations (view parameters), we can quicly reach some 10 000 URL or more. For example, Google says (with an enormous approximation) that theirs servers knows (and by so regulary invokes) 210 000 URLs for the http://share.ez.no website
  • Let’s calculate the number of SQL queries for each cache creation: this number depends only on the complexity of the templates, generaly, a drop down menu (or the hyped XL menus) needs several hundreds of queries, let’s say 300 SQL queries
  • Let’s imaginate that the directive stays as it is, without « expiry » nor «ignore_content_expiry », which is usually the case. We obtain a frequency of expiry of that cache of about 2 hours (at best) MORE at each content modification (unpredictable but potentially frequent). Let’s remains optimistic with the range of 2 hours.
  • The result : each day (24 hours), our drop down menu generates 10 000 URL * 12 expiry * 300 SQL queries = 36 milltions of SQL queries (and 10 000 template-block files). If we add the other usual « cache-block » (around metas, footer, columns...), we can imagine the impact of such a directive on a high traffic website. We can imagine also the impact of a robot that would invoke URLs « randomly », in this case, in addition to generate a huge, unnecessary burden, this directive could cause a gradual filling of the hard drive.

How to build out own key?

The question to ask during the reconstruction of a key is : « What are the different possible states of the content inside the block? ». For example, our famous drop down menu generally contains very little states, like for example the marking of the main section with a color or a CSS. In this example, a menu with 5 inputs must therefore have a key with only 6 possible values (« default », « folder 1 », « folder 2 », « folder 3 », « folder 4 », « folder 5 »), coupled with a coherent expiry directive (once per day, ignoring content expiry):

{cache-block keys=$folder_name ignore_content_expiry expiry=86400}

Create as many caches as there is possible values of $folder_name, which expires once a day, without expiring at during a content publication.



The « expiry » parameter

By default, without a particular directive, the expiration time of "template-blocks" associated with each "cache-block" is as follow:

  • 2 hours, if there no publication has occured during this period
  • at each new publication

The 'expiry' directive allows to define another timeout for expiration in seconds (0 seconds = never), and must be coupled with 'ignore_content_expiry' to neutralize the impact of publications on this expiry.

{cache-block ignore_content_expiry expiry=86400}
Creating a single version of cache, which expires once a day, without expiring during content publication
{cache-block ignore_content_expiry expiry=0}
Creating a single version of cache, which never expires



The « ignore_content_expiry » parameter

As it has been already explained with the oter directives, without the use of the 'ignore_content_expiry' directive, a 'template-block' expires at each new publication.

Generally, the “cache-blocks” allows to cache ( "template-block" ) the pagelayout.tpl elements such as metedata,header, footer or between rows of blocks in the right column.

It is rarely relevant to expire a set of "template-blocks" at each content publication, few functional needs can justify such a setting. A strong contributory website (forums, comments etc..) could see his "template-blocks" expire far too often and for no good reason.

It is therefore strongly recommended to:

  • Always use the 'ignore_content_expiry' directive on the ‘cache-blocks’
  • If however a block should regulary expire after a publication (latest news for example), if possible use the 'subtree_expiry' directive.
  • If the content that would trigger the expiry of the block is completely transversal, it becomes necessary to consider alternatives:
    • Create a "magical node" (without any children) at the root of the website, place a ‘subtree_expiry’ on this node and force a modification of this node following the publication of transversal contents (using a custom edit handler or a workflow)
    • Use an AJAX alternative
    • Use an alternative via ESI, if an ESI interpreter is available on the infrastructure (Varnish, Squid)



The « subtree_expiry » parameter

As explained above, the default expiration behavior of "template-blocks" on each content publication is a little too "broad" to be optimized. The 'subtree_expiry' thus allows to filter content that should cause an expiry on update, depending on its location in the content tree.

{cache-block subtree_expiry='news/'}
Creating a single version of cache, that expires following the publication of each news
Or by specifying the root node_id of the subtree (more stable over time than the alias)
{cache-block subtree_expiry=142}



Summary of common situations and recommended settings

This summary table shows the common situations of a real live website and the recommended “cache-block” expiry directives. It should be noted that these guidelines are very dependent on issues related to content refresh rate. The question to ask is : Am I ready to leave this block cached 1 or 2 hours even though a new content is available?


Content block type Recommended settings
scripts includes ignore_content_expiry
CSS includes ignore_content_expiry
or with an ezJSCore context (default):
keys=array($module_result.uri, ...)
or with an ezJSCore context (tricky):
keys=first_set( ezpagedata().persistent_variable.js_files, array('0'))|unique()|asort()
Menu includes keys=$folder_name
Latest news block subtree_expiry='news/'
Tag cloud block ignore_content_expiry
Latest forum posts ignore_content_expiry

A common and ricky situation is still the use of keys of the URI type, for example to conditioning the construction:

  • of the TITLE, METAs and other elements in the HEADER : Some can be get around by using persistent variables (see the example of the TITLE in ezwebin), others require the use of the $module_result.uri key, such as CSS includes by eZJSCore). It remains important to cut / embed its « cache-block » in relevance with their real need for uniqueness key
  • A possible but complex workaround for eZJScore could be to calculate the key value related to the JS and CSS arrays to include, for instance:
    keys=first_set( ezpagedata().persistent_variable.js_files, array('0'))|unique()|asort()



36 542 Users on board!

Tutorial menu


Printer Friendly version of the full article on one page with plain styles


Proudly Developed with from