Skip to content

Shopware 6 Performance Tuning: Getting the Most Out of Elasticsearch, Redis, and HTTP Cache

Published on Jun 5, 2025 | approx. 3 min read |

A slow shop costs revenue. Various studies show that users abandon a page if it takes longer than three seconds to load. Shopware 6 provides all the tools needed to achieve fast load times even with large product catalogs and high traffic — you just have to use them correctly.

1. Elasticsearch / OpenSearch for Product Search and Listings

Shopware 6 natively supports Elasticsearch and OpenSearch. Without a search engine, Shopware uses its own DAL (Data Abstraction Layer) with MySQL/MariaDB for all product queries — which becomes noticeably slower starting at around 10,000 products.

Installation and Activation

# In .env
SHOPWARE_ES_ENABLED=1
SHOPWARE_ES_HOSTS=localhost:9200
SHOPWARE_ES_INDEXING_ENABLED=1
SHOPWARE_ES_INDEX_PREFIX=sw

# Build the initial index
php bin/console es:index
php bin/console es:create:alias

Important Configuration in config/packages/shopware.yaml

shopware:
    elasticsearch:
        enabled: true
        hosts:
            - '%env(SHOPWARE_ES_HOSTS)%'
        index_prefix: '%env(SHOPWARE_ES_INDEX_PREFIX)%'
        throw_exception: true
        # Enable product fields for aggregations
        product:
            custom_fields_mapping:
                my_custom_field_text:
                    type: text
                    fields:
                        keyword:
                            type: keyword

Pitfalls

  • Re-indexing after changes: Every product change triggers a re-index. When making bulk changes, keep the Message Queue supervisor running.
  • Mapping changes: New custom fields require running es:index again.
  • Heap size: Elasticsearch requires at least 1 GB of heap — configure it in jvm.options: -Xms1g -Xmx1g.

2. Redis for Session, Cache, and Queue Storage

Redis significantly accelerates Shopware in three areas: session storage, object cache, and as a message queue backend.

Configuring Redis

# config/packages/framework.yaml
framework:
    session:
        handler_id: 'redis://localhost:6379/0'
    cache:
        app: cache.adapter.redis
        system: cache.adapter.redis_tag_aware
        pools:
            cache.adapter.redis:
                adapter: cache.adapter.redis
                provider: 'redis://localhost:6379/1'

Redis for the Shopware Cache

# config/packages/shopware.yaml
shopware:
    cache:
        invalidation:
            delay: 0
            count: 150

In config/packages/prod/framework.yaml:

framework:
    cache:
        prefix_seed: '%env(APP_SECRET)%'
        app: cache.adapter.redis_tag_aware
        pools:
            cache.app:
                tags: true

Redis Connection Pool with Sentinel (High Availability)

framework:
    cache:
        pools:
            cache.app:
                adapter: cache.adapter.redis_tag_aware
                provider: 'redis+sentinel://sentinel1:26379,sentinel2:26379,sentinel3:26379?redis_sentinel=mymaster'

Message Queue on Redis

# config/packages/messenger.yaml
framework:
    messenger:
        transports:
            async:
                dsn: 'redis://localhost:6379/messages'
                options:
                    auto_setup: false
                    delete_after_ack: true

3. HTTP Cache (Varnish / Symfony Reverse Proxy)

Shopware supports two HTTP cache backends: the built-in Symfony reverse proxy and Varnish. The HTTP cache makes pages extremely fast for non-logged-in users because no PHP execution is required.

Activating the Built-in HTTP Cache

The HTTP cache is activated via environment variables — Shopware handles the kernel configuration internally. Manual changes to public/index.php are not necessary.

In .env:

SHOPWARE_HTTP_CACHE_ENABLED=1
SHOPWARE_HTTP_CACHE_DEFAULT_TTL=7200

Cache Tags and Invalidation

Shopware uses cache tags to invalidate precisely. When a product is changed, only pages containing that product are removed from the cache.

<?php

declare(strict_types=1);

namespace MyPlugin\Subscriber;

use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Storefront\Framework\Cache\CacheResponseSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class ProductInvalidationSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            'product.written' => 'onProductWritten',
        ];
    }

    public function onProductWritten(EntityWrittenEvent $event): void
    {
        foreach ($event->getIds() as $productId) {
            // Invalidate the cache tag for this product
            // Shopware handles this automatically via the EntityCacheKeyGenerator
        }
    }
}

Configuring Varnish

For high-traffic setups, Varnish is the better choice. Shopware ships a default.vcl template:

# In .env
SHOPWARE_HTTP_CACHE_ENABLED=1
SHOPWARE_HTTP_REVERSE_PROXY_ENABLED=1
SHOPWARE_HTTP_REVERSE_PROXY_HOSTS=http://localhost:6081
SHOPWARE_HTTP_REVERSE_PROXY_TTL=7200

4. Database Optimization

Not to be neglected: the database. Shopware uses MariaDB/MySQL. Important settings:

# my.cnf / mariadb.conf.d/shopware.cnf
[mysqld]
innodb_buffer_pool_size = 2G          # 70-80% of RAM
innodb_log_file_size = 256M
query_cache_type = 0                  # Removed in MySQL 8 anyway
max_connections = 300
thread_cache_size = 16

Identifying missing indexes:

-- Find slow queries
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 0.5;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';

5. Asset Optimization

Shopware automatically compresses and bundles assets. Important for production environments:

php bin/console asset:install
php bin/console theme:compile
# Then Brotli/gzip compression via nginx

Conclusion

Performance tuning in Shopware is not a one-time event but an ongoing process. The three most important measures after a base setup:

  1. Elasticsearch for large product catalogs (starting at ~10,000 products)
  2. Redis for session, cache, and message queue
  3. HTTP Cache for all non-personalized pages

With this combination, load times under 500ms are achievable even on complex shops.

Thomas Wunner

Thomas Wunner

Certified IT specialist for application development with an instructor qualification and over 14 years of experience building scalable web applications with Symfony and Shopware. When not coding, Thomas volunteers as a lifeguard with the Wasserwacht, performs as a DJ, and explores the countryside on his motorbike.

Comments

Comments are provided by Remark42. By loading comments, data is transmitted to our comment server.