Improving Plone 3 Product Performance

6 min read

(For more resources on Plone, see here.)


CMS Plone provides:

  • A Means of adding, editing, and managing content
  • A database to store content
  • A mechanism to serve content in HTML or other formats

Fortunately, it also supplies the tools to do all these things in an incredibly easy and powerful way. For example, content producers can create a new article without worrying how it will look or what other information will be surrounding the main information.

To do this Plone must compose a single HTML output file (if we are talking from a web browser viewpoint) by joining and rendering several sources of data according to the place, importance, and target they are meant for.

As it is built upon the Zope application server, all these jobs are easy for Plone. However, they have a tremendous impact as far as work and performance goes. If enough care is not taken, then a whole website could be stuck due to a couple of user requests.

In this article, we’ll look at the various performance improvements and how to measure these enhancements.

We are not going to make a comprehensive review of all the options to tweak or set up a Zope-based web application, like configuring a like configuring a proxy cache or a load balancer. There are lots of places, maybe too many, where you can find information about these topics. We invite you to read these articles and tutorials and subscribe or visit Zope and Plone mailing lists:

Installing CacheFu with a policy product

When a user requests HTML pages from a website, many things can be expressed about the downloading files by setting special headers in the HTTP response. If managed cautiously, the server can save lots of time and, consequently, work by telling the browser how to store and reuse many of the resources it has got.

CacheFu is the Plone add-on product that streamlines HTTP header handling in order to obtain the required performance.

We could add a couple of lines to the buildout.cfg file to download and install CacheFu. Then we could add some code in our end user content type products ( and Products.poxContentTypes) to configure CacheFu properly to deliver them in an efficient way.

However, if we do so, we would be forcing these products to automatically install CacheFu, even if we were testing them in a development environment.

To prevent this, we are going to create a policy product and add some code to install and configure CacheFu.

A policy product is a regular package that will take care of general customizations to meet customer requirements. For information on how to create a policy product see Creating a policy product.

Getting ready

To achieve this we’ll use pox.policy, the policy product created in Creating a policy product.

How to do it…

    1. Automatically fetch dependencies of the policy product: Open in the root pox.policy folder and modify the install_requires variable of the setup call:


      # -*- Extra requirements: -*-

    2. Install dependencies during policy product installation. In the profiles/default folder, modify the metadata.xml file:

      <?xml version=”1.0″?>

You could also add here all the other products you plan to install as dependencies, instead of adding them individually in the buildout.cfg file.

    1. Configure products during the policy product installation. Our policy product already has a <genericsetup:importStep /> directive in its main component configuration file (configure.zcml). This import step tells GenericSetup to process a method in the setuphandlers module (we could have several steps, each of them with a matching method). Then modify the setupVarious method to do what we want, that is, to apply some settings to CacheFu.

      from import getSite
      from Products.CMFCore.utils import getToolByName
      from config import *

      def setupVarious(context):

      if context.readDataFile(‘pox.policy_various.txt’) is None:
      portal = getSite()

      # perform custom operations
      # Get portal_cache_settings (from CacheFu) and
      # update plone-content-types rule
      pcs = getToolByName(portal, ‘portal_cache_settings’)
      rules = pcs.getRules()
      rule = getattr(rules, ‘plone-content-types’)
      rule.setContentTypes(list(rule.getContentTypes()) +

The above code has been shortened for clarity’s sake. Check the accompanying code bundle for the full version.

  1. Add or update a file in your package with all configuration options:

    # Content types that should be cached in plone-content-types
    # rule of CacheFu
    CACHED_CONTENT = [‘XNewsItem’, ‘Video’,]

  2. Build your instance up again and launch it:

    ./bin/instance fg

  3. After installing the pox.policy product (it’s automatically installed during buildout as explained in Creating a policy product) we should see our content types—Video and XNewsItem—listed within the cached content types.

    The next screenshot corresponds to the following URL: http://localhost:8080/plone/portal_cache_settings/with-caching-proxy/rules/plone-content-types.

The with-caching-proxy part of the URL matches the Cache Policy field; and the plone-content-types part matches the Short Name field.

As we added Python code, we must test it.

  • Create this doctest in the README.txt file in the pox.policy package folder:

    Check that our content types are properly configured

    >>> pcs = getToolByName(self.portal, ‘portal_cache_settings’)
    >>> rules = pcs.getRules()
    >>> rule = getattr(rules, ‘plone-content-types’)
    >>> ‘Video’ in rule.getContentTypes()
    >>> ‘XNewsItem’ in rule.getContentTypes()

  • Modify the tests module by replacing the ptc.setupPloneSite() line with these ones:

    # We first tell Zope there’s a CacheSetup product available

    # And then we install pox.policy product in Plone.
    # This should take care of installing CacheSetup in Plone also

  • And then uncomment the ZopeDocFileSuite:

    # Integration tests that use PloneTestCase
    ‘README.txt’, package=’pox.policy’,

  • Run this test suite with the following command:

    ./bin/instance test -s pox.policy

How it works…

In the preceding steps, we have created a specific procedure to install and configure other products (CacheFu in our case). This will help us in the final production environment startup as well as on installation of other development environments we could need (when a new member joins the development team, for instance).

In Step 1 of the How to do it… section, we modified to download and install a dependency package during the installation process, which is done on instance buildout. Getting dependencies in this way is possible when products are delivered in egg format thanks to Python eggs repositories and distribution services.

If you need to get an old-style product, you’ll have to add it to the [productdistros] part in buildout.cfg.

Products.CacheSetup is the package name for CacheFu and contains these dependencies: CMFSquidTool, PageCacheManager, and PolicyHTTPCacheManager.

There’s more…

For more information about CacheFu visit the project home page at

You can also check for its latest version and release notes at Python Package Index (PyPI, a.k.a. The Cheese Shop):

The first link that we recommended in the Introduction is a great help in understanding how CacheFu works:

See also

  • Creating a policy product
  • Installing and configuring an egg repository


Please enter your comment!
Please enter your name here