PrestaShop Smarty Cache vs OPcache vs Browser Cache

379 views

Understanding the Three Caching Layers in PrestaShop

PrestaShop uses multiple caching mechanisms to deliver pages quickly. Each layer operates at a different level of the stack, and understanding what each one does, when it kicks in, and when you need to clear it is essential for both performance tuning and troubleshooting. The three most important caching layers are Smarty template cache, PHP OPcache, and browser cache. They work together, but they solve different problems and require different management approaches.

When a customer visits your store, the request passes through all three layers in reverse order. The browser checks its local cache first. If it has a fresh copy of the resource, it never contacts your server at all. If the browser does send a request, PHP processes it. OPcache ensures that PHP files are compiled once and reused from memory rather than being re-parsed on every request. Finally, Smarty cache ensures that template rendering, which involves parsing template syntax and executing template logic, happens only when necessary rather than on every page load.

Problems arise when these layers serve stale content. You change a template file, but the page looks the same. You update a PHP file, but the old behavior persists. You modify CSS, but the browser still shows the old styles. Each of these symptoms points to a different caching layer, and clearing the wrong one wastes time without solving the problem.

Smarty Template Cache: How It Works

Smarty is the template engine that PrestaShop uses to render HTML. Every .tpl file in your theme and modules goes through Smarty before it becomes HTML that gets sent to the browser. Smarty caching operates in two distinct phases: compilation and output caching.

Template Compilation

When Smarty encounters a .tpl file for the first time, it compiles it into a PHP file. This compiled file is stored in the /var/cache/prod/smarty/compile/ directory (or /var/cache/dev/smarty/compile/ in debug mode). The compiled file contains the template logic translated into pure PHP, which executes much faster than parsing the Smarty syntax on every request.

Smarty checks whether the compiled version is up to date by comparing timestamps. If the source .tpl file is newer than the compiled version, Smarty recompiles it automatically. This is controlled by the compile_check setting. In production, you can disable compile checking for maximum performance, which means Smarty assumes compiled templates are always current and never checks the source files.

Template Output Caching

Beyond compilation, Smarty can also cache the rendered output of templates. When output caching is enabled, Smarty stores the final HTML output of a template and serves it directly on subsequent requests without executing any of the template logic. This is more aggressive than compilation caching because it skips not just the parsing step but also the data processing and logic execution within the template.

Output caching in PrestaShop is managed per module hook. Each module can declare whether its hook output is cacheable, and PrestaShop assigns cache keys based on factors like the current language, shop, currency, and customer group. This means a French customer and an English customer get separate cached versions.

Smarty Cache Settings in PrestaShop

You configure Smarty caching in the back office under Advanced Parameters > Performance. The relevant settings are:

Template compilation: This controls how Smarty handles template compilation. The options are typically "Never recompile" (fastest, uses compiled version always), "Recompile if changed" (checks file timestamps, good balance), and "Force compile" (recompiles every request, for development only). In production, use "Recompile if changed" unless you are certain your templates never change between deployments, in which case "Never recompile" provides a small additional performance gain.

Cache: This toggles Smarty output caching. When enabled, Smarty stores the rendered HTML output and serves it without re-executing template logic. This provides significant performance benefits for stores with complex templates or many module hooks. The cache type can be set to filesystem (default) or a custom caching handler.

Multi-front optimizations: This enables caching across multiple front-end servers. Only relevant for clustered setups.

Clear cache: Options include "Never clear cache files," "Clear cache every time something is modified," and specific clearing strategies. For most stores, clearing on modification is the right choice because it ensures updates are visible immediately while still benefiting from caching between changes.

Clearing Smarty Cache

To clear Smarty cache manually, you can use the "Clear cache" button in the Performance page of the back office. This deletes compiled templates and cached output from the /var/cache/ directory. You can also clear it by deleting files directly from the server:

Delete compiled templates: remove contents of var/cache/prod/smarty/compile/

Delete cached output: remove contents of var/cache/prod/smarty/cache/

You need to clear Smarty cache when you modify .tpl template files (if compile checking is disabled), when you install or update a module that changes templates, when you switch themes, or when you modify template-related configuration. If you change a .tpl file and the change does not appear on the front end, Smarty compile cache is almost always the cause.

PHP OPcache: How It Works

PHP OPcache is a bytecode cache built into PHP. When PHP executes a script, it goes through three stages: lexing (breaking the source code into tokens), parsing (building an abstract syntax tree), and compiling (generating bytecode that the PHP engine executes). OPcache stores the compiled bytecode in shared memory so that subsequent requests for the same script skip the lexing, parsing, and compilation stages entirely.

This is different from Smarty cache. Smarty caches template rendering output (HTML). OPcache caches PHP compilation output (bytecode). They operate at completely different levels. A Smarty template that has been compiled into a PHP file by Smarty still benefits from OPcache because that compiled PHP file itself gets cached as bytecode by OPcache.

OPcache Configuration for PrestaShop

OPcache is configured in your php.ini file. The most important settings for PrestaShop are:

opcache.enable=1 turns OPcache on. This should always be enabled in production. The performance difference is dramatic: PHP execution becomes 2 to 5 times faster with OPcache enabled.

opcache.memory_consumption=256 sets the amount of shared memory (in megabytes) available for storing compiled bytecode. PrestaShop with several modules can easily consume 128MB or more. If this is set too low, OPcache evicts older entries to make room for new ones, which defeats the purpose. Set this to 256MB or higher for stores with many modules. You can check usage with opcache_get_status() to see how much memory is actually consumed.

opcache.max_accelerated_files=20000 sets the maximum number of PHP files that can be cached. PrestaShop core plus modules can easily have 10,000 or more PHP files. The actual value used by OPcache is rounded up to the next prime number from a predefined set, so setting 20000 results in an actual limit of 20479. Check opcache_get_status() to verify you are not hitting this limit.

opcache.validate_timestamps=1 tells OPcache to check whether source files have changed. When enabled, OPcache checks the file modification time at intervals defined by revalidate_freq. In production, you can set this to 0 (disabled) for maximum performance, but you must then restart PHP-FPM or call opcache_reset() whenever you deploy new code.

opcache.revalidate_freq=60 defines how often (in seconds) OPcache checks for file changes when validate_timestamps is enabled. A value of 60 means OPcache checks each file at most once per minute. Higher values mean better performance but longer delays before code changes take effect. For active development, set this to 0 or 2. For production, 60 is a good balance.

opcache.interned_strings_buffer=16 allocates memory for interned strings, which PHP uses to deduplicate identical strings across different scripts. PrestaShop benefits from this because many modules share the same class names, function names, and string literals. Set this to 16MB or higher.

opcache.save_comments=1 must be enabled for PrestaShop. PrestaShop and some of its dependencies use PHP DocBlock annotations that are read at runtime. If you disable this, certain features break.

OPcache and the CLI vs Web Split

An important detail about OPcache is that the CLI (command line) and web (PHP-FPM or mod_php) environments maintain separate OPcache pools. Clearing OPcache from the command line (for example, running a PHP script that calls opcache_reset() via CLI) does not clear the web OPcache. To clear the web OPcache, you must either restart the PHP-FPM service, or execute opcache_reset() through a web request.

This distinction matters in deployment workflows. If you deploy new code and clear OPcache via a CLI command, your website continues serving the old bytecode until the web OPcache is also cleared. Many deployment tools handle this by hitting a special URL endpoint that triggers opcache_reset(), or by restarting PHP-FPM as part of the deployment process.

When to Clear OPcache

You need to clear OPcache whenever you modify, upload, or replace PHP files on your server. This includes deploying a new version of PrestaShop, installing or updating modules, editing PHP files directly on the server, and updating Composer dependencies. If you change a PHP file and the old behavior persists despite the file being clearly modified on disk, OPcache is serving the old bytecode. Restarting PHP-FPM is the most reliable way to clear it.

Browser Cache: How It Works

Browser caching is the final layer, and it operates entirely on the client side. When a browser downloads a resource (CSS file, JavaScript file, image, font, or even an HTML page), it can store a local copy and reuse it for subsequent requests. This eliminates network round trips entirely for cached resources, which is the single biggest performance improvement possible because no server-side optimization can beat zero network latency.

Browser caching is controlled by HTTP response headers that your server sends along with each resource. The most important headers are Cache-Control, Expires, ETag, and Last-Modified.

Cache-Control Header

The Cache-Control header is the primary mechanism for controlling browser caching. It supports several directives:

max-age=31536000 tells the browser to cache the resource for up to 31,536,000 seconds (one year). During this period, the browser uses its local copy without contacting the server at all. This is ideal for static assets like CSS, JavaScript, and images that include a version identifier in their URL (like a hash or query string).

no-cache does not mean "do not cache." It means the browser may cache the resource but must validate it with the server before using the cached copy. The server responds with either a 304 (Not Modified) status, meaning the cached version is still good, or a 200 with the new content.

no-store actually prevents caching. The browser must download the resource fresh every time. Use this for sensitive content that should never be stored locally.

public indicates that the response can be cached by any cache, including CDNs and proxy servers. Use this for static assets.

private indicates that the response is specific to a single user and should not be cached by shared caches like CDNs. Use this for pages that contain user-specific content, like a customer's account page or cart.

ETag Header

An ETag (Entity Tag) is a unique identifier for a specific version of a resource. The server generates it (typically a hash of the file content) and sends it with the response. When the browser needs to validate its cached copy, it sends the ETag back to the server in an If-None-Match header. The server compares the ETags and returns either 304 (use your cached version) or 200 (here is the new version).

ETags are useful when you want browser caching with validation. The browser still makes a request to the server, but if the content has not changed, the server sends back a tiny 304 response instead of the full resource. This saves bandwidth while ensuring freshness.

Last-Modified and If-Modified-Since

These headers work similarly to ETags but use timestamps instead of content hashes. The server sends the Last-Modified timestamp with the resource, and the browser sends it back as If-Modified-Since when validating. The server checks whether the file has been modified since that time and returns 304 or 200 accordingly.

ETags are generally preferred over Last-Modified because they are based on content rather than time, which avoids issues with clock synchronization and is more precise. However, most servers send both, and browsers use whichever is available.

Browser Cache Configuration for PrestaShop

PrestaShop's static assets (CSS, JavaScript, images) should be cached aggressively by browsers. The standard approach is to configure your web server to add appropriate Cache-Control headers to static file responses.

For Apache, you use the mod_expires and mod_headers modules in your .htaccess file. PrestaShop's default .htaccess includes some caching rules, but you may want to extend them. A typical configuration sets max-age=31536000 for images, fonts, CSS, and JavaScript files, while HTML responses get no-cache to ensure fresh content.

For Nginx, you add expires directives in your location blocks for static files. For example, location ~* \.(css|js|jpg|png|gif|ico|woff2)$ { expires 1y; add_header Cache-Control "public, immutable"; } caches static assets for one year and marks them as immutable (telling the browser not to even validate them).

Cache Busting in PrestaShop

If you set long cache lifetimes for CSS and JavaScript files, how do browsers get updated versions when you deploy changes? This is where cache busting comes in. PrestaShop handles this differently depending on whether CCC (Combine, Compress, Cache) is enabled.

With CCC enabled, PrestaShop combines CSS and JavaScript files into bundles and generates filenames that include a hash of the content. When the content changes, the filename changes, and browsers download the new file because they have never seen that URL before. This is the most reliable cache busting approach.

Without CCC, PrestaShop serves individual CSS and JavaScript files at their original URLs. Some themes and modules append a version query string (like ?v=1.2.3) to these URLs, which changes when the module is updated. Browsers treat the URL with a different query string as a different resource and download it fresh.

Images are trickier because their URLs typically do not change unless the image itself is replaced. If you replace an image with a new one at the same URL, browsers that have the old version cached will continue showing it until the cache expires. In this case, you need to either change the image filename or clear browser caches (which you cannot do for your visitors). The practical solution is to use versioned image URLs or wait for the cache to expire naturally.

How the Three Layers Interact

Understanding how these three caching layers interact is crucial for effective troubleshooting. Here is the lifecycle of a typical request:

A customer visits a product page. The browser checks its cache for the HTML of that page. Since HTML is typically served with no-cache, the browser sends a request to the server (possibly with an If-Modified-Since or If-None-Match header for validation).

The web server receives the request and passes it to PHP. PHP-FPM's OPcache has the bytecode for PrestaShop's index.php, the dispatcher, controllers, and all module files cached in shared memory. PHP executes the bytecode without recompiling any source files.

PrestaShop's controller calls Smarty to render the template. Smarty checks its cache for a compiled version of the template. If output caching is enabled and a valid cached output exists for this combination of language, customer group, and other cache keys, Smarty returns the cached HTML directly. If not, Smarty executes the compiled template (which OPcache has also cached as bytecode since compiled Smarty templates are PHP files), generates the HTML, stores it in the output cache, and returns it.

PHP sends the HTML response to the browser, along with HTTP headers that control browser caching. The browser renders the HTML and requests any CSS, JavaScript, and image files referenced in it. For each of these assets, the browser checks its local cache. If it has a fresh copy (based on Cache-Control max-age), it uses the local copy without contacting the server. If the cached copy needs validation, it sends a conditional request with ETag or If-Modified-Since headers.

Troubleshooting Stale Content

When changes you make do not appear on the front end, you need to identify which caching layer is responsible. Here is a systematic approach:

Step 1: Check the Browser

Open the page in an incognito or private browsing window, or do a hard refresh (Ctrl+Shift+R on most browsers). If the change appears in incognito but not in a normal window, browser cache is the cause. Clear the browser cache or wait for it to expire.

For CSS and JavaScript changes specifically, check the network tab in browser DevTools. Look at the response headers for the file you changed. If the response shows a 304 (Not Modified) and the content is old, the server-side file may not have actually changed (check OPcache). If the browser is not even making a request for the file (it shows "from disk cache" or "from memory cache"), the Cache-Control max-age has not expired.

Step 2: Check Smarty Cache

If the change does not appear even in incognito, the issue is server-side. For template changes, clear Smarty cache from the back office (Advanced Parameters > Performance > Clear cache) or delete the contents of var/cache/prod/smarty/. Reload the page and check if the change appears.

Step 3: Check OPcache

If clearing Smarty cache does not help and the change involves a PHP file (not a template), OPcache is likely serving old bytecode. Restart PHP-FPM or call opcache_reset() through a web request. On shared hosting where you cannot restart PHP-FPM, your hosting control panel may have an option to clear OPcache, or you can create a small PHP file that calls opcache_reset() and access it through your browser.

Step 4: Check Other Caches

PrestaShop has additional caching mechanisms beyond these three layers. The Symfony cache (in PrestaShop 1.7 and 8.x) stores compiled Symfony service containers, route definitions, and other framework data. Clear it by deleting var/cache/prod/ and var/cache/dev/ directories. If you use a reverse proxy like Varnish or a CDN like Cloudflare, those add yet another caching layer that must be cleared separately.

Optimal Configuration for Production

For a production PrestaShop store, the optimal caching configuration balances performance with maintainability:

Smarty: Set template compilation to "Recompile if changed." Enable output caching. Set cache clearing to "Clear on modification." This gives you strong caching performance while ensuring that back office changes (like editing CMS pages or changing module configuration) take effect immediately.

OPcache: Enable with at least 256MB memory, 20000 max accelerated files, validate_timestamps enabled with revalidate_freq of 60 seconds. This configuration means code changes take up to 60 seconds to take effect, which is acceptable for production. If you deploy code changes infrequently and want maximum performance, disable validate_timestamps and restart PHP-FPM after each deployment.

Browser Cache: Set Cache-Control with long max-age values (at least one month, ideally one year) for static assets (CSS, JavaScript, images, fonts). Use no-cache for HTML responses so pages are always validated. Enable CCC in PrestaShop to get content-hashed filenames for combined CSS and JavaScript files, which provides automatic cache busting when assets change.

With this configuration, your store benefits from all three caching layers working together. Static assets are served from browser cache without any server contact. PHP files are executed from cached bytecode without recompilation. And template rendering is cached so that Smarty logic runs only when content changes. The result is a store that loads quickly for returning visitors and handles high traffic efficiently on the server side.

When to Clear Each Cache Layer

To avoid both stale content and unnecessary cache clearing, follow these guidelines:

Clear Smarty cache when you edit .tpl files, change module positions or hooks, install or update modules that modify templates, or change theme-related settings. You do not need to clear Smarty cache when you change PHP files or when you update CSS or JavaScript files.

Clear OPcache when you edit PHP files, install or update modules, update PrestaShop core, or run Composer to update dependencies. You do not need to clear OPcache for template or CSS changes.

Clear browser cache when you need to see CSS, JavaScript, or image changes immediately during development. For production, rely on cache busting (versioned URLs, CCC hash filenames) instead of asking users to clear their caches. You cannot control your visitors' browser caches, so your deployment process must account for this by using proper cache busting techniques.

A comprehensive cache clearing sequence after a major deployment would be: clear Smarty compile and cache directories, restart PHP-FPM to clear OPcache, purge your CDN or reverse proxy cache if applicable, and verify in an incognito browser window. For minor changes (like editing a single template), clearing only the relevant layer is sufficient and faster.

For more details, read our guides: PrestaShop Cache: Full Page Cache Modules Explained and Redis Cache for PrestaShop: Setup and Performance Gains.

Was this answer helpful?

Still have questions?

Can't find what you're looking for? Send us your question and we'll get back to you quickly.

Loading...
Back to top