CI/CD
.yml
GitLab · Magento · Suchindex · Queue · Cache-Warmup
Zero-Downtime: Suchindex, Queue-Lag
und Cache-Warmup zusammendenken

Der Symlink-Switch ist nur der Anfang. Suchindex-Reindex, Queue-Consumer-Neustart und Cache-Warmup sind die drei verborgenen Wartezeiten nach jedem Magento-Deployment – und sie müssen in der Pipeline koordiniert werden.

14 Min. Lesezeit OpenSearch · RabbitMQ · Redis · Cache-Warmup · Queue-Consumer Magento 2.4 · GitLab CI/CD

1. Die drei verborgenen Downtime-Quellen nach dem Deploy

Der Symlink-Switch in Magento-Deployments ist atomar und dauert Millisekunden. Wer danach annimmt, das Deployment sei abgeschlossen, übersieht drei Schichten, die den Unterschied zwischen einer guten Nutzererfahrung und sichtbaren Degradierungen ausmachen. Die erste Schicht ist der Suchindex: Nach einem Deployment mit Schema-Änderungen in OpenSearch oder Elasticsearch muss der Index neu aufgebaut werden. Bis das abgeschlossen ist, können Suchergebnisse unvollständig oder fehlerhaft sein.

Die zweite Schicht sind die Queue-Consumer. Magento nutzt Message Queues über RabbitMQ oder die MySQL-basierte Fallback-Implementierung für asynchrone Verarbeitung: Bestellbestätigungen, Indexer-Updates, Newsletter-Versand, Preisberechnungen. Queue-Consumer, die während des Deployments laufen, arbeiten mit dem alten Code. Nach dem Symlink-Switch müssen sie neu gestartet werden, damit sie den neuen Code verwenden. Ohne kontrollierten Neustart können Queue-Consumer minuten- oder stundenlang mit dem alten Code laufen – oder abstürzen, wenn der alte Code mit der neuen Datenbank inkompatibel ist.

Die dritte Schicht ist der Cache-Warmup. Nach einem Cache-Flush antwortet Magento auf die ersten Requests langsamer, weil alle Caches kalt sind. Bei hoher Last kann das zu spürbaren Latenzspitzen führen, die in Monitoring-Systemen als Incident erscheinen, obwohl das Deployment selbst fehlerfrei war. Ein koordinierter Cache-Warmup nach dem Deployment verhindert diese Latenzspitzen, indem wichtige Seiten vorab aufgerufen und gecacht werden.

2. Suchindex: Warum Reindex nicht immer sofort nötig ist

Nicht jeder Reindex muss unmittelbar nach dem Deployment ausgeführt werden. Magento unterscheidet zwischen verschiedenen Indexer-Typen mit unterschiedlichen Auswirkungen. Ein Reindex des Produktkatalogs ist oft zeitaufwändig – bei großen Katalogen kann er Stunden dauern. Wenn das Deployment keine Änderungen am Katalogsschema oder an der Suchkonfiguration enthält, ist ein vollständiger Reindex nicht notwendig.

Die wichtige Unterscheidung: Partielle Indexer-Updates (indexer:reindex catalogsearch_fulltext) sind häufig deutlich schneller als ein vollständiger Reindex aller Indexer. Für Deployments ohne Schema-Änderungen reicht es, die Indexer im Modus Update by Schedule laufen zu lassen, der Änderungen asynchron verarbeitet. Die Entscheidung, welche Indexer nach welchem Deployment neu aufgebaut werden müssen, sollte im Deployment-Prozess dokumentiert und nicht ad hoc getroffen werden.

3. Reindex kontrolliert in die Pipeline einbauen

Ein Reindex-Job in der GitLab-Pipeline läuft idealerweise als asynchroner Schritt nach dem Symlink-Switch, aber vor dem Verify-Job. Er sollte über eine Variable gesteuert werden, die pro Deployment gesetzt werden kann. So können Releases ohne Schema-Änderungen den Reindex-Job überspringen, während Releases mit Elasticsearch-Mappingänderungen ihn zwingend auslösen.

# Controlled search index rebuild after deployment
reindex:search:
  stage: verify
  variables:
    # Set FORCE_REINDEX=1 for deployments with catalog schema changes
    FORCE_REINDEX: "0"
  script:
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
    - |
      if [ "$FORCE_REINDEX" = "1" ]; then
        ssh "$DEPLOY_USER@$DEPLOY_HOST" bash -s << 'SSH'
        set -euo pipefail
        cd "$DEPLOY_PATH/current"
        # Rebuild only the search index — not all indexers
        bin/magento indexer:reindex catalogsearch_fulltext
        echo "Search index rebuild complete"
        # Verify index status
        bin/magento indexer:status catalogsearch_fulltext
        SSH
      else
        echo "FORCE_REINDEX not set — skipping full reindex"
        echo "Invalidating search cache only"
        ssh "$DEPLOY_USER@$DEPLOY_HOST" \
          "cd $DEPLOY_PATH/current && bin/magento cache:clean full_page"
      fi
  needs:
    - deploy:production
  when: on_success
  only:
    - tags

4. Queue-Consumer: Pause, Drain und sicherer Neustart

Queue-Consumer müssen während eines Deployments kontrolliert behandelt werden. Das naive Vorgehen – einfach weiterlaufen lassen – führt dazu, dass Consumer nach dem Symlink-Switch mit dem neuen current-Verzeichnis arbeiten, aber PHP-Prozesse, die bereits gestartet wurden, noch auf den alten Code zugreifen. Das ist besonders kritisch bei Deployments mit Datenbankmigrationen: Ein alter Queue-Consumer kann versuchen, mit dem alten Schema-Zustand Daten zu schreiben, die das neue Schema erwartet.

Das sichere Muster: Vor dem Symlink-Switch die Queue-Consumer stoppen oder pausieren (bin/magento queue:consumers:stop), nach dem Switch neu starten. Der Drain-Schritt stellt sicher, dass alle aktuell verarbeiteten Nachrichten abgeschlossen werden, bevor die Consumer gestoppt werden. Das vermeidet verloren gegangene Nachrichten. Bei RabbitMQ-basierten Setups kann die Queue weiter Nachrichten empfangen, während die Consumer gestoppt sind – sie werden nach dem Neustart verarbeitet, was Queue-Lag erzeugt, aber keine verlorenen Nachrichten.

5. Queue-Consumer in der GitLab-Pipeline steuern

Die Steuerung der Queue-Consumer gehört in den Deploy-Job, nicht in ein manuelles Betriebshandbuch. Ein Deploy-Job, der Queue-Consumer nicht behandelt, ist für Deployments mit Datenbankmigrationen unvollständig. Der folgende YAML-Block zeigt das sichere Muster für Queue-Consumer-Verwaltung im Deployment-Kontext.

# Queue consumer management integrated into the deploy job
deploy:production:
  stage: deploy
  script:
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
    - RELEASE_ID=$(date +%Y%m%d-%H%M%S)
    - RELEASE_PATH="$DEPLOY_PATH/releases/$RELEASE_ID"
    # Transfer artifact to new release directory
    - ssh "$DEPLOY_USER@$DEPLOY_HOST" "mkdir -p $RELEASE_PATH"
    - rsync -az --delete ./ "$DEPLOY_USER@$DEPLOY_HOST:$RELEASE_PATH/"
    - |
      ssh "$DEPLOY_USER@$DEPLOY_HOST" bash -s << 'SSH'
      set -euo pipefail
      # Stop queue consumers before symlink switch (prevents old-code processing)
      # This command requires Magento 2.4+ with queue:consumers:stop support
      cd "$DEPLOY_PATH/current"
      bin/magento queue:consumers:stop --wait-for-running-processes || true
      # Link shared resources and switch symlink atomically
      RELEASE_PATH="$DEPLOY_PATH/releases/$RELEASE_ID"
      ln -sfn "$DEPLOY_PATH/shared/app/etc/env.php" "$RELEASE_PATH/app/etc/env.php"
      ln -sfn "$DEPLOY_PATH/shared/pub/media" "$RELEASE_PATH/pub/media"
      ln -sfn "$RELEASE_PATH" "$DEPLOY_PATH/current"
      # Post-switch: flush cache and restart consumers with new code
      cd "$DEPLOY_PATH/current"
      bin/magento cache:flush
      # Restart queue consumers — systemd or supervisor depending on setup
      systemctl restart magento-queue-consumers || supervisorctl restart magento:*
      SSH
  when: manual
  only:
    - tags

6. Cache-Warmup: Strategie für die wichtigsten Seiten

Ein Cache-Flush ohne anschließenden Warmup hinterlässt ein Magento-System mit vollständig kaltem Cache. Die ersten Requests nach dem Deployment treffen auf unkonditionierte PHP-Prozesse, die alle Caches neu aufbauen müssen: Block-Cache, Layout-Cache, Config-Cache, Full-Page-Cache. Dieser Zustand dauert typischerweise mehrere Minuten bei einem mittelgroßen Shop. In dieser Zeit sind Ladezeiten deutlich erhöht und können zu Abbrüchen bei Nutzern führen.

Die Warmup-Strategie priorisiert Seiten nach ihrer Bedeutung: Startseite, wichtigste Kategorieseiten, meistbesuchte Produktseiten. Ein einfaches Warmup-Skript ruft diese Seiten per curl auf und erzwingt so die Cache-Generierung. Fortgeschrittene Implementierungen nutzen Magento-native Tools wie bin/magento cache:warm oder externe Cache-Warming-Services wie Varnish-Warming-Scripts. Der Warmup sollte in der Verify-Stage nach dem Deploy-Job ausgeführt werden, sobald der Health-Check bestätigt hat, dass das neue Release antwortet.

7. Cache-Warmup automatisiert in der Verify-Stage

Der Cache-Warmup in der GitLab-Pipeline ist ein Verify-Stage-Job, der nach dem erfolgreichen Deployment die wichtigsten URLs aufruft. Die URL-Liste sollte als Variable oder als Datei im Repository verwaltet werden, damit sie einfach aktualisiert werden kann, wenn sich die Seitenstruktur des Shops ändert. Ein Warmup-Job, der die falschen Seiten aufruft, ist nutzlos; einer, der die richtigen Seiten aufruft, reduziert Post-Deployment-Latenz messbar.

# Cache warmup job — runs after successful deployment verification
warmup:cache:
  stage: verify
  variables:
    SHOP_BASE_URL: "https://shop.mironsoft.de"
    WARMUP_TIMEOUT: "30"
  script:
    # Health check first — only warm cache if site responds
    - curl -f --max-time 10 "$SHOP_BASE_URL/health" || exit 1
    # Warm the most important pages sequentially
    - |
      PAGES=(
        "/"
        "/sale.html"
        "/herren.html"
        "/damen.html"
        "/neuheiten.html"
        "/customer/account/login"
        "/checkout/cart"
      )
      for page in "${PAGES[@]}"; do
        echo "Warming: $SHOP_BASE_URL$page"
        curl -s -o /dev/null -w "%{http_code} %{time_total}s" \
          --max-time "$WARMUP_TIMEOUT" \
          -H "X-Cache-Warmup: 1" \
          "$SHOP_BASE_URL$page" || true
        echo ""
      done
    # Verify full page cache is now active
    - |
      CACHE_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
        --max-time 10 "$SHOP_BASE_URL/")
      echo "Homepage status after warmup: $CACHE_STATUS"
      [ "$CACHE_STATUS" = "200" ] || exit 1
  needs:
    - deploy:production
  when: on_success
  only:
    - tags

8. Timing: Reihenfolge der Post-Deploy-Schritte

Die Reihenfolge der Post-Deploy-Schritte ist nicht beliebig. Queue-Consumer müssen vor dem Symlink-Switch gestoppt werden, damit sie keine alten Nachrichten mit dem neuen Code oder neuen Nachrichten mit dem alten Code verarbeiten. Der Symlink-Switch selbst ist der atomare Kern des Deployments. Unmittelbar danach folgt der Cache-Flush, der alle Magento-Caches leert. Dann kommt der Queue-Consumer-Neustart mit dem neuen Code. Erst wenn die Consumer laufen und der Health-Check grün ist, kann der Cache-Warmup beginnen.

Der Reindex sollte nach dem Cache-Warmup und nach dem Queue-Consumer-Neustart ausgeführt werden, da er I/O-intensiv ist und Konkurrenz mit dem Warmup-Traffic vermieden werden sollte. Ein vollständiger Reindex kann je nach Kataloggröße Minuten bis Stunden dauern und sollte deshalb außerhalb der Stoßzeiten oder in einem separaten, manuell ausgelösten Job geplant werden. Die klare Reihenfolge dieser Schritte ist der Unterschied zwischen einem koordinierten und einem improvisierten Post-Deploy-Prozess.

9. Koordiniert vs. unkoordiniert: direkter Vergleich

Der Unterschied zwischen einem koordinierten und einem unkoordinierten Post-Deploy-Prozess zeigt sich nicht sofort, sondern in den Stunden nach einem Deployment. Unkoordinierte Prozesse hinterlassen sichtbare Lücken: Suchergebnisse zeigen veraltete Daten, Queue-Consumer verarbeiten Nachrichten mit dem falschen Code, Nutzer bemerken deutlich erhöhte Ladezeiten. Koordinierte Prozesse schließen diese Lücken systematisch.

Post-Deploy-Aspekt Unkoordiniert Koordiniert (GitLab-Pipeline) Auswirkung
Suchindex Manuell oder vergessen Pipeline-Job mit Variable Saubere Suchergebnisse ab Minute 1
Queue-Consumer Laufen mit altem Code weiter Stop vor Switch, Start danach Keine Schema-Inkompatibilitäten
Cache-Warmup Nutzer wärmen den Cache auf Automatisch nach Verify Keine Latenzspitzen nach Deploy
Reindex-Timing Gleichzeitig mit Warmup Nach Warmup, außerhalb Stoßzeit Geringere Server-Last
Fehlerdiagnose Keine Log-Struktur Pipeline-Logs je Schritt Schnelle Ursachenanalyse

Die Investition in koordinierte Post-Deploy-Schritte ist überschaubar. Die drei Jobs – Reindex, Queue-Consumer-Neustart und Cache-Warmup – können in wenigen Stunden in eine bestehende Pipeline integriert werden. Die Einsparungen in Form von vermiedenen Incidents, kürzeren Latenzspitzen und schnellerer Fehlerdiagnose übersteigen den Aufwand bei der ersten Produktion-Nutzung.

10. Zusammenfassung

Zero-Downtime bei Suchindex, Queue-Lag und Cache-Warmup zusammendenken bedeutet, den Deployment-Prozess über den Symlink-Switch hinaus zu denken. Der Switch selbst ist der schnellste Schritt; die drei Post-Deploy-Schichten sind die eigentliche Herausforderung. Suchindex-Reindex muss pro Deployment bewusst entschieden werden – nicht immer notwendig, aber wenn, dann koordiniert. Queue-Consumer müssen vor dem Switch gestoppt und danach mit dem neuen Code neu gestartet werden. Cache-Warmup verhindert Latenzspitzen nach dem Deploy und schützt die Nutzererfahrung in den ersten Minuten nach dem Release.

In der GitLab-Pipeline werden diese drei Schritte als Jobs in der Verify-Stage implementiert, die nach dem erfolgreichen Deploy-Job laufen. Jeder Job ist einzeln konfigurierbar, einzeln beobachtbar und einzeln debuggbar. Das ist der Unterschied zwischen einem Deployment-Prozess, der beim Symlink-Switch endet, und einem, der erst dann abgeschlossen ist, wenn der Shop vollständig und performant antwortet.

Zero-Downtime: Suchindex, Queue und Cache — Das Wichtigste auf einen Blick

Suchindex

Nicht nach jedem Deploy nötig. FORCE_REINDEX-Variable steuert, ob catalogsearch_fulltext neu aufgebaut wird.

Queue-Consumer

Stoppen vor dem Symlink-Switch, neu starten danach. Verhindert Schema-Inkompatibilitäten bei Datenbankmigrationen.

Cache-Warmup

Nach Verify-Health-Check die wichtigsten Seiten vorab aufrufen. Verhindert Latenzspitzen in den ersten Minuten nach dem Deploy.

Reihenfolge

Consumer stoppen → Symlink-Switch → Cache-Flush → Consumer starten → Health-Check → Warmup → Reindex (bei Bedarf).

11. FAQ: Zero-Downtime bei Suchindex, Queue und Cache-Warmup

1Muss nach jedem Deploy ein Reindex ausgeführt werden?
Nein. Nur bei Schemaänderungen, Elasticsearch/OpenSearch-Mapping-Änderungen oder geänderten Suchkonfigurationen. Bei reinen Code-Deploys reicht "Update by Schedule".
2Was passiert wenn Consumer während Deploy laufen?
Sie können nach dem Symlink-Switch mit dem neuen Code im alten Kontext arbeiten. Bei DB-Migrationen führt das zu Schema-Inkompatibilitäten. Consumer stoppen vor Switch, neu starten danach.
3Wie lange dauert ein Cache-Warmup?
Für 10–20 wichtige Seiten 30–120 Sekunden. Warmup auf kritischste Seiten beschränken – Startseite, Top-Kategorien, meistbesuchte Produkte.
4Reindex und Warmup parallel?
Nicht empfohlen. Reindex belastet I/O und CPU, was Warmup-Requests verlangsamt. Warmup zuerst, dann Reindex starten.
5Was ist Queue-Lag?
Anwachsen unverarbeiteter Nachrichten während der Consumer-Pause. Temporär, wird nach dem Neustart abgebaut. Keine Nachrichten gehen verloren.
6Maintenance-Mode für Consumer-Stop notwendig?
Nein. bin/magento queue:consumers:stop stoppt Consumer ohne Maintenance-Mode. Das ist der bevorzugte Ansatz für Zero-Downtime-Deployments.
7Wie Seiten für Warmup priorisieren?
Nach Traffic-Volumen aus Analytics: Startseite, Toplevel-Kategorien, meistbesuchte Produkte. Liste im Repository als Datei pflegen.
8Wie Consumer in Magento 2.4 neu starten?
Über systemd, Supervisor oder bin/magento queue:consumers:start. Methode hängt vom Server-Setup ab – muss im Deployment-Skript explizit definiert sein.
9catalogsearch_fulltext vs. andere Indexer?
catalogsearch_fulltext rebuildet den Volltext-Suchindex in OpenSearch und ist I/O-intensiv. Andere Indexer wie catalog_product_price sind oft schneller.
10Wie erkenne ich, dass Warmup funktioniert hat?
Per HTTP-Response-Header: Varnish setzt X-Cache: HIT, Magento FPC setzt X-Magento-Cache-Control: public. curl -I gegen die aufgewärmten URLs prüfen.