Skip to main content
Version: 2026.2

Performance Guide

This guide covers configuration changes and tools to optimize the performance of a Pimcore application. Each section includes benchmark results from ApacheBench for comparison.

Before testing, set the following environment variables to replicate a production scenario:

APP_ENV=prod
APP_DEBUG=0
PIMCORE_DEV_MODE=0

PHP OPcache and JIT Compiler

OPcache stores precompiled script bytecode in shared memory, removing the need for PHP to load and parse scripts on each request. PHP 8 added Just-In-Time Compilation (JIT), which can further improve performance. The JIT compiler requires OPcache to be enabled.

By default, JIT is disabled. Enable it in your php.ini:

opcache.enable=1           # enables OPcache for PHP server
opcache.enable_cli=1 # enables OPcache for CLI mode
opcache.jit_buffer_size=256M # JIT buffer memory size. 0 disables JIT.

Benchmarks

ab -n 100 -c 20 http://localhost/en

  • Before (OPcache on, JIT off): 212ms mean per request
  • After (OPcache on, JIT on): 202ms mean per request

Symfony Performance Best Practices

Since Pimcore is built on Symfony, follow the Symfony Performance Best Practices.

Benchmarks

ab -n 100 -c 20 http://localhost/en

  • Before: 220ms mean per request
  • After: 208ms mean per request

OPcache Preloading

OPcache preloading preloads commonly used framework files and keeps the generated byte-code in memory.

Configure in php.ini:

opcache.preload_user=www-data  # user that runs PHP-FPM
opcache.preload=/var/www/html/var/cache/prod/App_KernelProdContainer.preload.php

Note: memory_limit should be at least 200M when using preloading with Pimcore.

You can control which classes are preloaded using Symfony service tags container.preload and container.no_preload.

Benchmarks

ab -n 100 -c 20 http://localhost/en/shop/Products/Cars/Economy-Cars/Fiat-500~p104

  • Before: 115ms mean per request
  • After: 94ms mean per request

MySQL/MariaDB Optimizations

Composite Indexes

If you use Data Objects or custom database tables, configure composite indexes so the query optimizer can use them instead of scanning the full table. You can configure composite indexes in the class definition under General Settings.

Buffer Pool

The InnoDB buffer pool caches table and index data in memory. Set innodb_buffer_pool_size to 70-80% of total available memory on a dedicated database server.

[mysqld]
innodb_buffer_pool_size=5G # adjust according to your data

See this discussion for guidance on choosing the right size. You can also use MySQLTuner for additional optimization suggestions.

Benchmarks

ab -n 100 -c 20 http://localhost/en/shop/Products/Cars/Economy-Cars~c547

  • Before: 503ms mean per request
  • After: 450ms mean per request

Pimcore Caching (Redis)

Pimcore uses a primary object cache where every element (document, asset, data object) is cached as a serialized object. By default, this cache uses the Doctrine database adapter and writes to the cache_items table. For a significant performance boost, switch to the Redis adapter.

Configure Redis for the Pimcore cache pool:

# config/packages/cache.yaml
framework:
cache:
pools:
pimcore.cache.pool:
public: true
default_lifetime: 31536000 # 1 year
adapter: cache.adapter.redis_tag_aware
provider: '%env(REDIS_URL)%'

After clearing the cache (e.g. during a deployment), warm it up so users experience optimal performance even on first access:

bin/console pimcore:cache:warming

By default, pimcore:cache:warming caches 20 items per iteration and waits 2 seconds between iterations. Adjust with --perIteration and --timeoutBetweenIteration.

Benchmarks

ab -n 100 -c 20 http://localhost/en/shop/Products/Cars~c390

  • Before: 1299ms mean per request
  • After: 1112ms mean per request

Full Page Cache

Pimcore's full page cache stores complete controller action responses. Subsequent requests for the same page are served directly from the cache without going through the MVC cycle.

pimcore:
full_page_cache:
enabled: true
lifetime: 120
exclude_cookie: 'pimcore_admin_sid'
exclude_patterns: '@^/test/de@'

Important: Only use sessions when necessary. The Pimcore full-page cache detects session usage and disables itself if a session is active.

Benchmarks

ab -n 100 -c 20 http://localhost/en

  • Before: 141ms mean per request
  • After: 129ms mean per request

Static Page Generator

Pimcore can generate static HTML files from documents. These static files are served directly by Apache/Nginx without going through the PHP/MVC cycle. This is best suited for pages with content that does not change frequently (not recommended for dynamic pages like news listings or product pages).

To enable: go to Document > Settings > Static Page Generator, check the enable checkbox, optionally define a lifetime, and save.

Benchmarks

ab -n 100 -c 20 http://localhost/en/Magazine

  • Before: 161ms mean per request
  • After: 7ms mean per request

In-Template Caching

Pimcore provides the pimcore_cache Twig extension for caching parts of a template independently from the global cache. This is useful for template sections that involve heavy computation or load many objects, such as navigation menus.

{% set cache = pimcore_cache("main_navigation_cache", 60) %}
{% if not cache.start() %}
{% set navStartNode = document.getProperty('navigation_root') %}

{% if not navStartNode is instanceof('\\Pimcore\\Model\\Document') %}
{% set navStartNode = pimcore_document(1) %}
{% endif %}

{% set mainNavigation = app_navigation_data_links(document, navStartNode) %}
<div class="container">
...
{{
pimcore_render_nav(mainNavigation, 'menu', 'renderMenu', {
maxDepth: 2,
ulClass: {
0: 'navbar-nav menu-links ml-4 m-auto',
1: 'dropdown dropdown-menu',
'default': 'dropdown-menu dropdown-submenu'
}
})
}}
...
</div>
{% do cache.end() %}
{% endif %}

Benchmarks

ab -n 100 -c 20 http://localhost/en/Magazine

  • Before: 162ms mean per request
  • After: 129ms mean per request

Varnish Cache

Varnish is a caching reverse proxy placed in front of your web server. On the initial request, Varnish saves a copy of the response in memory. Subsequent requests are served directly from memory without reaching the application server.

Pimcore sends the correct headers for Varnish when the full-page cache is enabled.

Edge Side Includes (ESI)

ESI is a markup standard for managing page fragments that can be cached individually and assembled into a single page. Fragments can have their own cache policies and be shared across multiple pages.

Symfony has built-in support for ESI. See the Symfony ESI documentation. Learn more about Varnish.

ESI tags are not compatible with the Static Page Generator.