Terug naar blog
magentoperformancecachingoptimization

Magento performance optimalisatie: een praktische gids

20 november 202510 min leestijd

Bij high-traffic Magento shops is performance geen feature maar een vereiste. Een 100ms vertraging kost 1% conversie. In dit artikel behandelen we production-grade optimalisaties: Varnish VCL configuratie voor Magento-specifieke edge cases, Redis architectuur voor session clustering, MySQL query profiling en indexing strategieën. Gebaseerd op ervaring met shops die 10.000+ concurrent users verwerken.

Varnish VCL: beyond de basis configuratie

Magento's standaard VCL mist cruciale optimalisaties. Custom VCL voor grace mode, saint mode en intelligente cache warming maakt het verschil tussen een stabiele en een falende Black Friday:

vcl 4.1;
 
import std;
import directors;
 
backend default {
    .host = "127.0.0.1";
    .port = "8080";
    .probe = {
        .url = "/health_check.php";
        .timeout = 2s;
        .interval = 5s;
        .window = 5;
        .threshold = 3;
    }
    .first_byte_timeout = 300s;
    .connect_timeout = 5s;
    .between_bytes_timeout = 2s;
}
 
sub vcl_recv {
    set req.grace = 6h;
 
    set req.url = std.querysort(req.url);
 
    if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|gclid|fbclid)=") {
        set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|gclid|fbclid)=[^&]+", "");
        set req.url = regsuball(req.url, "\?(utm_source|utm_medium|utm_campaign|gclid|fbclid)=[^&]+&?", "?");
        set req.url = regsub(req.url, "\?$", "");
    }
 
    if (req.method == "POST" && req.url ~ "/graphql") {
        if (req.http.X-GraphQL-Operation ~ "mutation") {
            return (pass);
        }
    }
}
 
sub vcl_backend_response {
    if (beresp.http.X-Magento-Tags) {
        set beresp.do_esi = true;
    }
 
    if (beresp.status >= 500 && beresp.status < 600) {
        set beresp.saintmode = 30s;
        if (req.method != "POST") {
            return (retry);
        }
    }
 
    if (bereq.url ~ "\.(css|js|jpg|jpeg|png|gif|ico|woff2?)$") {
        set beresp.ttl = 365d;
        unset beresp.http.Set-Cookie;
    }
}

Grace mode is essentieel: bij backend overload serveert Varnish cached content tot 6 uur oud. Dit voorkomt cascade failures tijdens traffic spikes. Saint mode markeert backends tijdelijk als unhealthy bij 5xx errors.

Redis: session clustering en cache segmentatie

Een enkele Redis instance is een single point of failure én een bottleneck. Optimale setup: gescheiden instances voor sessions, cache en FPC met correcte eviction policies:

'session' => [
    'save' => 'redis',
    'redis' => [
        'host' => 'redis-session.internal',
        'port' => '6379',
        'timeout' => '2.5',
        'persistent_identifier' => 'sess',
        'database' => '0',
        'compression_threshold' => '2048',
        'compression_library' => 'lz4',
        'max_concurrency' => '20',
        'break_after_frontend' => '5',
        'break_after_adminhtml' => '30',
        'first_lifetime' => '600',
        'bot_first_lifetime' => '60',
        'bot_lifetime' => '7200',
        'disable_locking' => '1',
        'min_lifetime' => '60',
        'max_lifetime' => '2592000',
        'sentinel_master' => 'mymaster',
        'sentinel_servers' => 'sentinel1:26379,sentinel2:26379,sentinel3:26379',
    ]
],
'cache' => [
    'frontend' => [
        'default' => [
            'backend' => 'Magento\Framework\Cache\Backend\Redis',
            'backend_options' => [
                'server' => 'redis-cache.internal',
                'port' => '6379',
                'database' => '0',
                'compress_data' => '1',
                'compression_lib' => 'lz4',
                'preload_keys' => [
                    'EAV_ENTITY_TYPES',
                    'GLOBAL_PLUGIN_LIST',
                    'DB_IS_UP_TO_DATE',
                    'SYSTEM_DEFAULT'
                ]
            ]
        ],
        'page_cache' => [
            'backend' => 'Magento\Framework\Cache\Backend\Redis',
            'backend_options' => [
                'server' => 'redis-fpc.internal',
                'port' => '6379',
                'database' => '0',
                'compress_data' => '0'
            ]
        ]
    ]
]

Critische insight: disable_locking op sessions voorkomt lock contention die bij hoge concurrency tot timeouts leidt. De preload_keys optie warmt de meest gebruikte cache entries direct na flush.

MySQL query profiling en index optimalisatie

Magento's EAV model genereert complexe queries. Zonder proper indexing degradeert performance exponentieel met catalogus grootte. Systematische profiling identificeert bottlenecks:

SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 0.5;
SET GLOBAL log_queries_not_using_indexes = 'ON';
 
SELECT
    ea.attribute_code,
    ea.backend_type,
    COUNT(*) as usage_count
FROM catalog_product_entity_varchar cpev
JOIN eav_attribute ea ON cpev.attribute_id = ea.attribute_id
WHERE ea.entity_type_id = 4
GROUP BY ea.attribute_id
HAVING usage_count > 1000
ORDER BY usage_count DESC;
 
ALTER TABLE catalog_product_index_price
    ADD INDEX idx_website_customer_price (website_id, customer_group_id, min_price);
 
ALTER TABLE catalog_product_entity
    ADD INDEX idx_listing_cover (type_id, attribute_set_id, entity_id, sku, created_at);

Real-world tip: de catalog_product_flat tabel escaleert niet bij 100k+ producten. Disable flat tables en optimaliseer EAV queries met proper covering indexes.

Async operations en queue processing

Synchrone operations tijdens checkout zijn conversion killers. Verplaats alles wat niet direct nodig is naar async queues:

namespace Ten50\Module\Model\Queue;
 
use Magento\Framework\MessageQueue\PublisherInterface;
use Magento\Sales\Api\Data\OrderInterface;
 
class OrderPostProcessor
{
    private const TOPIC_INVENTORY = 'inventory.reservations.update';
    private const TOPIC_INDEX = 'product.index.update';
 
    public function __construct(
        private PublisherInterface $publisher
    ) {}
 
    public function afterPlace(OrderInterface $order): void
    {
        $this->publisher->publish(
            self::TOPIC_INVENTORY,
            json_encode([
                'order_id' => $order->getEntityId(),
                'items' => $this->extractSkuQty($order)
            ])
        );
 
        $productIds = array_column($order->getAllItems(), 'product_id');
        $this->publisher->publish(
            self::TOPIC_INDEX,
            json_encode(['product_ids' => array_unique($productIds)])
        );
    }
}

Run consumers via supervisor met auto-restart. Benchmark: checkout tijd reduceerde van 3.2s naar 0.8s door inventory updates en email verzending naar async te verplaatsen.

Performance audit nodig?

Wij analyseren uw Magento stack van Varnish tot MySQL en implementeren gerichte optimalisaties met meetbare resultaten.

Neem contact op