PHPackages                             colinmollenhour/cm\_diehard - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Caching](/categories/caching)
4. /
5. colinmollenhour/cm\_diehard

ActiveMagento-module[Caching](/categories/caching)

colinmollenhour/cm\_diehard
===========================

Cm\_Diehard: Full-Page Cache

136631[1 issues](https://github.com/colinmollenhour/Cm_Diehard/issues)[1 PRs](https://github.com/colinmollenhour/Cm_Diehard/pulls)PHP

Since Jan 6Pushed 4mo ago26 watchersCompare

[ Source](https://github.com/colinmollenhour/Cm_Diehard)[ Packagist](https://packagist.org/packages/colinmollenhour/cm_diehard)[ RSS](/packages/colinmollenhour-cm-diehard/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (2)Used By (0)

Cm\_Diehard: Full-Page Cache
============================

[](#cm_diehard-full-page-cache)

This module aims to make it easy to serve up cacheable HTML pages without falling back to fully-dynamic pages as soon as the visitor takes an individualized action like adding a product to their cart. It has several cache backend models to choose from and supports dynamic block replacement via Ajax, ESI (edge-side includes) or non-Ajax Javascript. This hole-punching is only performed as-needed by using a cookie to keep track of which blocks (if any) need to be dynamic. The backends also differ in the way that cache invalidation is handled by using some interesting techniques; some of which allow for *real-time* cache invalidation even with a caching reverse proxy! The rendering technique allows for users with dynamic blocks to still warm the cache for other users to further increase the cache hit rate.

For a sample implementation of `Cm_Diehard` for OpenMage see [Cm\_DiehardSample](https://github.com/colinmollenhour/Cm_DiehardSample).

Backends
--------

[](#backends)

There are currently three backends and three hole-punching (injection) methods. Not all backends support all injection methods. The backend and supported injection methods are:

- Local Backend
    - Javascript (supports "Early Flush", similar to Facebook's "BigPipe" method)
    - Ajax
    - ESI
- Proxy Backend
    - Ajax
    - ESI
- Revalidating Backend
    - Ajax
    - ESI

Note that all injection methods use a single injection point rather than one for every "hole".

### Local Backend

[](#local-backend)

This backend is like the Enterprise FPC except it currently uses Javascript (but not Ajax) for hole punching. It does a lightweight cached response by default, and appends the dynamic blocks to the response. The purpose for this backend is mainly to make testing easier in the absence of a reverse proxy although it should still have much better performance than no caching at all (600% improvement on a clean install).

This backend may use either the OpenMage app cache instance (default), or a separately configured cache instance by configuring `global/diehard_cache/backend` and `global/diehard_cache/backend_options`.

#### Pros

[](#pros)

- Drop-in and go, no additional requirements
- Offers additional flexibility when determining if cached response should be used
- Cache clearing and invalidation is handled instantly and automatically
- Experimental: can do dynamic replacement without using Ajax

#### Cons

[](#cons)

- OpenMage is still loaded (but, controller is only dispatched when necessary)

To enable this backend you must add it as a request processor to `app/etc/local.xml`:

```

            ...

                Cm_Diehard_Model_Backend_Local

            1
            1

            ...

                ...

```

### Proxy Backend

[](#proxy-backend)

This backend renders the response generically and uses hole-punching with Ajax or ESI as needed. Cache invalidation is handled by dumping a list of URLs to invalidate to a file and the actual invalidation of those URLs on the reverse proxy is left up to you.

### Revalidating Backend

[](#revalidating-backend)

This backend is like the Proxy backend in that it uses HTTP headers to signal the upstream reverse proxy to cache the response, but it uses the "must-revalidate" cache control feature of HTTP to make the reverse proxy revalidate every request. Revalidation requests are handled by a base init of OpenMage and are therefore very lightweight in the case of a cache hit. This makes it easy to use a caching reverse proxy upstream without explicitly invalidating large numbers of cached pages on a potentially large numbers of edge servers. Safely use a CDN for your html and still enjoy real-time invalidation! Ajax and ESI hole-punching are supported.

ETag or Last-Modified headers are used to communicate if the cached content is stale so make sure your proxy supports revalidation and choose the proper method. Weak ETags are used since byte-range requests are not supported.

Pros:

- Off-loads storage of cache to remote server keeping outbound bandwidth for hits at the edge for scalability.
- Requires no direct invalidation on the remote server since every request is revalidated.
- You can use CDNs/proxies for your cache frontend and still have instant invalidation with no custom integration - eliminating weird bugs or race conditions.
- Can be used with the browser's cache for easy testing in a dev environment with no CDN. Cons:
- Every request will still hit PHP, but the cache hit will be *much* more efficient than a miss and use negligible bandwidth.

Reverse-proxy servers:

- Squid (IMS: Yes, INM: NO)
- Nginx (IMS: Yes, INM: Partial)
- Apache (IMS: Yes, INM: buggy, possibly fixed in 2.4)
- Varnish (IMS: Yes, INM: No (experimental-ims branch for 3.x series maybe)

Third-party services that definitely support revalidation:

- Cloudfront

Third-party services that probably support revalidation (unconfirmed):

- Akamai
- Limelight
- EdgeCast

To use this backend you must add it to the cache request processors in `app/etc/local.xml`:

```

                Cm_Diehard_Model_Backend_Revalidating

```

Enabling Cache
--------------

[](#enabling-cache)

By default, no caching is enabled by `Cm_Diehard`. There are three methods of enabling caching but in all cases it is recommended to implement your caching scheme in a separate module from `Cm_Diehard`. A falsey value (0, null, false, '') for the cache lifetime disables caching for the current page.

For a sample implementation of `Cm_Diehard` for OpenMage see [Cm\_DiehardSample](https://github.com/colinmollenhour/Cm_DiehardSample).

### config.xml

[](#configxml)

Set the lifetime in seconds based on the full action name in `config.xml`:

```

                86400
                86400

```

### Layout updates

[](#layout-updates)

Every block inherits a new method named "setDiehardCacheLifetime" which takes the desired lifetime in seconds. Layout updates will override the values in config.xml.

```

            300

```

### Event observers, controllers, blocks, etc..

[](#event-observers-controllers-blocks-etc)

In any code before the `http_response_send_before` event is dispatched, you can set the lifetime using the 'diehard' helper. The helper is added to the OpenMage registry with the key 'diehard' so that you can easily make your code not dependent on Cm\_Diehard.

```
    Mage::registry('diehard') && Mage::helper('diehard')->setLifetime(300);
```

Public vs Private Domain
------------------------

[](#public-vs-private-domain)

You must take care that when caching is enabled for a page that you don't render anything that is specific to an individual visitor. The classic example is the "My Cart" link in the header which displays the number of items in the cart and the "Log In"/"Log Out" links. There are many ways to handle these private or "dynamic" blocks in cached pages. In general you must render generically for the cached responses and then regularly for the hole-punching responses. Here are some methods:

### Placeholders only

[](#placeholders-only)

With this method the block will render only an empty div used as a placeholder for cached responses and then regularly for dynamic block injection. The advantage of this method is that no templates need to be modified or added and no block class overrides are needed, just a simple layout update.

```

        1

```

```
