"Bot-Last"

"JTL-Shop langsam durch Bots: Erst messen, dann behandeln"

"Der Shop wird zäh, vereinzelt 504er, und im eigenen Haus hat sich nichts geändert. Die naheliegende Diagnose - die Merkmalfilter - trifft nur bei manchen Shops zu. 16 Monate Zugriffsprotokolle zeigen, was wirklich passiert: zwei verschiedene Krankheiten mit ähnlichen Symptomen."

Kurz gesagt

"Bot-Last im JTL-Shop hat zwei Ursachen, die man nicht verwechseln darf: die schiere Menge an Crawl-Aufrufen (Treiber) und teure Filterkombinationen (Verstärker). Die Diagnosekennzahl ist Requests je Besuch - rund 5 bei echten Kunden, über 100 bei automatisiertem Verkehr. Gegen die Menge hilft auf Standard-Hosting wenig, gegen die Filter ein Code-Block in config.JTL-Shop.ini.php."

Der Shop wird zäh. Vereinzelt 504er. Im eigenen Haus hat sich nichts geändert - keine neue Extension, kein Datenbank-Update, keine Werbeaktion. Was passiert da? Die erste Vermutung im JTL-Forum ist fast immer dieselbe: die Merkmalfilter. Die zweite ist Cloudflare. Beides stimmt manchmal - aber meistens nicht.

Was gerade passiert

Die Zahl der Crawler wächst. Nicht nur klassische Suchmaschinen, sondern zunehmend KI-Crawler - GPTBot, ClaudeBot, Amazonbot, Bytespider, PerplexityBot. Im JTL-Forum beschreiben mehrere Händler dasselbe Bild: Der Shop ist nicht langsam, er wird langsam gemacht (Thread 247645, Thread 244786). Ein Händler berichtet: 90 Prozent seines Verkehrs kommen mittlerweile von Bots.

Das Problem ist kein Einzelfall mehr. Aber die Diagnose, die am häufigsten gestellt wird, ist zu eng.

Die Menge - der Treiber

Crawler holen sich den gesamten Shop. Nicht gezielt Filter, sondern alles: Produktseiten, Kategorien, Bilder, Startseite. In einer Frequenz, für die der Shop nie ausgelegt war.

"Liniendiagramm: Anfragen je Tag an einen JTL-Shop von Mai 2025 bis August 2026, mit sprunghaftem Anstieg ab November 2025"
"Anfragen je Tag an einen JTL-Shop, 476 Tage aus dem Zugriffsprotokoll. Bis Oktober 2025 rund 2.000 bis 3.000 am Tag, danach ein Sprung auf das Vierzigfache. Spitzentag: 576.382."
16 Monate gemessen, ein JTL-Shop mit 9.000 Artikeln

Mai 2025: 3.323 Anfragen pro Tag. Juli 2026: 230.148 - das 69-Fache. Der Sprung kam im November 2025, innerhalb eines Monats. In derselben Woche tauchen fünf KI-Crawler erstmals auf: Amazonbot, ClaudeBot, meta-externalagent, Bytespider, PerplexityBot.

Spitzentag: 576.382 Anfragen am 3. August 2026. Nur 10,8 Prozent des Verkehrs gibt sich als Bot zu erkennen - der Rest sieht aus wie ein Browser.

Quelle: 16 Monate Apache-Zugriffsprotokolle, anonymisiert zitierbar.

Das allein bringt die Hardware an die Grenze. Der PHP-Worker-Pool läuft voll, echte Kunden bekommen 504er - noch bevor irgendein Filter im Spiel ist.

Das zweite Muster: schieres Volumen, das man nicht sieht

Ein zweiter Shop zeigt ein anderes Bild: kein einziger Ausschlag im Diagramm. Und trotzdem kommen 40 Prozent des Verkehrs von etwas, das kein Kunde sein kann. 23 Länder mit zusammen 856.047 Requests und null gezählten Besuchen. China allein: 6.369 Requests je Besuch.

Das ist die Signatur eines verteilten Netzes: viele Länder, viele IP-Adressen, je einzeln unauffällig, in der Summe die Hälfte der Serverlast. Genau die Konstellation, gegen die eine Sperre je IP nichts ausrichtet. Wer nur nach Ausschlägen im Diagramm sucht, findet diesen Shop nie.

Die Kennzahl, mit der man es selbst prüft

Die nützlichste einzelne Erkenntnis dieses Vorhabens: Requests je Besuch, geteilt je Land. Man teilt die Anzahl der Anfragen durch die gezählten Besuche - zwei Spalten, die im Cloudflare-Dashboard frei verfügbar sind.

Herkunft Requests je Besuch Einordnung
Deutschland 4,8 Normalfall, echte Kunden
USA 9,5 erhöht
Türkei 43 auffällig
Finnland 140 eindeutig automatisiert
China 6.369 Massenautomatisierung

Der Referenzwert liegt bei rund 5 - in beiden Shops unabhängig voneinander gemessen. Alles über 20 verdient einen zweiten Blick. Über 100 ist keine Diskussion mehr. Quelle: Cloudflare-Auswertung zweier Shops, eine Woche im August 2026, anonymisiert.

Einschränkungen: Die Werte sind gesampelt, nicht exakt gezählt. „Besuche" ist eine Näherung über Seitenaufrufe mit externem Verweis. Das Herkunftsland ist nicht der Auftraggeber. Und „Requests" sind nicht „Seitenaufrufe" - in der Zahl stecken auch Bilder, CSS und JavaScript. Deshalb ist das Verhältnis aussagekräftig, die absolute Zahl allein nicht.

Zuerst messen, welche der beiden Krankheiten man hat

Bevor man irgendetwas unternimmt, muss man wissen, welches Problem man hat. Die Verteilung der Aufrufe nach Filtertiefe - doppelte Unterstriche im Pfad - ist die Messgröße, die beide Fälle unterscheidet:

Filtertiefe Anteil am Volumen Diagnose
kein __ 99,92 % -
ein __ 0,07 % -
zwei __ 0,01 % Mengenproblem
drei oder mehr ~0,00 % -

Zweistellige Prozente bei Tiefe zwei und mehr: Filterproblem. Promillebereich: Mengenproblem. Diese Unterscheidung ist der praktische Kern - sie entscheidet, welches Mittel greift.

Die Filter - der Verstärker

Hier kommen die stapelbaren Merkmalfilter ins Spiel. URLs wie /kategorieA__filter1__filter5__filter7 sind je Aufruf überproportional teuer: schlecht cachebar, viele Datenbankabfragen. Trifft ein Teil des Crawl-Volumens auf sie, kostet dieser Teil ein Vielfaches einer normalen Seite.

Seitentyp cachebar? Datenbanklast typische Bot-Frequenz
Startseite ja (statisch) gering hoch
Produktseite bedingt mittel hoch
Kategorieseite bedingt mittel hoch
Filterkombination (2+ Filter) nein hoch mittel

Aber: Die Filter sind nicht die Quelle der Masse. Im gemessenen Shop sind Filterpfade 0,08 Prozent aller Anfragen. Das Zweieinhalbfache von fast nichts ist immer noch fast nichts. Der Filterblock funktioniert einwandfrei - er ist nur an der falschen Stelle, wenn das Problem die Menge ist.

Ein größerer Server verschiebt die Grenze, löst aber nicht die Ursache. Mehr PHP-Worker halten länger durch, aber das Volumen wächst weiter.

Die Wege im Vergleich

Alle Wege nebeneinander. Jeder mit seinem Hintergrund: auf welcher Ebene er ansetzt, was er löst, was er kostet, wogegen er nicht hilft.

Weg Ebene Gegen Fläche oder Rate Was er löst Wogegen er nicht hilft
Filterkombinationen begrenzen / nicht verlinken Inhalt beide Entzieht dem Problem die Grundlage - für alle Crawler Schon gecrawlte URLs
noindex auf Filterseiten Inhalt Fläche (mittelbar) Verhindert Indexierung Abrufvolumen
robots.txt mit Mustern Inhalt Fläche (mittelbar) Reduziert Volumen bei regelkonformen Crawlern KI-Crawler, getarnte Bots
Cloudflare / Proxy Netzwerk beide (vor Server) Request erreicht den Server gar nicht -
Sperre im Shop (config.JTL-Shop.ini.php) Shop Rate auf Filter Spart DB-Last, punktuell wirksam Gesamtvolumen, Worker-Pool
Worker-Pool erhöhen Server Fläche (befristet) Verschiebt die Grenze Wurzelursache

Gegen das Mengenproblem (der Hauptfall) gibt es auf Standard-Hosting - Webspace, Shop-Backend, .htaccess, kein Root-Zugriff - kein wirksames Mittel, das die Zahl der Aufrufe senkt. Was in dieser Ausgangslage geht: die Kosten je Aufruf senken (Cache, Backend-Einstellungen) und Bots auf teuren URLs abweisen (der Code-Block unten). Was nicht geht: Ratenbegrenzung vor dem Server, ASN-Sperren, Challenge. Dafür braucht es Root-Zugriff oder einen Proxy.

Der Code-Block: Bots auf Filter-URLs abweisen

Der folgende Block wird in includes/config.JTL-Shop.ini.php eingefügt - den einzigen Ort im JTL-Shop, der bei Updates nicht überschrieben wird (belegt durch Praxis, nicht nur Dokumentation). Er weist Bots nur auf Filterkombinationen ab, nicht auf dem ganzen Shop - Produkt- und Kategorieseiten bleiben frei.

// UPBOX BEGIN: Bot-Abwehr auf gestapelten Filter-URLs
//
// Greift ab dem ZWEITEN Filter. Ein einzelner Filter bleibt frei: Die Zahl
// solcher Seiten waechst nur linear und sie haben SEO-Wert. Erst das Stapeln
// erzeugt kombinatorisch viele, schlecht cachebare, datenbankteure URLs.
//
// Kategorie-, Produkt- und Startseiten sind nie betroffen, statische Dateien
// ebenfalls nicht.

$upbox_uri  = $_SERVER['REQUEST_URI'] ?? '';
$upbox_pfad = strtok($upbox_uri, '?');

// Statische Dateien nie abweisen: Sie kosten keine Datenbankabfrage, und ein
// abgewiesenes Bild verschwindet aus der Bildersuche.
$upbox_asset = preg_match(
    '#.(jpe?g|png|gif|webp|avif|svg|ico|bmp|css|js|mjs|json|woff2?|ttf|otf|eot|map|pdf|txt|xml)$#i',
    $upbox_pfad
) === 1;

// Filtertiefe im Pfad: je gesetztem Filter ein doppelter Unterstrich.
$upbox_tiefe = $upbox_asset ? 0 : substr_count($upbox_pfad, '__');

// Filtertiefe im Query-String dazuzaehlen (nicht-SEO- oder Hybrid-URLs).
$upbox_query = (string)parse_url($upbox_uri, PHP_URL_QUERY);
if (!$upbox_asset && $upbox_query !== '') {
    $upbox_tiefe += preg_match_all('#(^|&)(fqd+|mfd*|h)=#', $upbox_query);
}

if ($upbox_tiefe >= 2) {
    // Zwei langsam alternde Signale statt einer Namensliste, die veraltet:
    // erstens die gebraeuchliche Selbstbezeichnung von Crawlern,
    // zweitens das gleichzeitige Fehlen typischer Browser-Kopfzeilen.
    $upbox_ua      = $_SERVER['HTTP_USER_AGENT'] ?? '';
    $upbox_crawler = preg_match('/(?:bot|spider)/i', $upbox_ua) === 1;

    // Alle drei muessen fehlen. Ein echter Besucher ohne Referer - Lesezeichen,
    // Verlauf, Link aus einer Mail - sendet trotzdem Accept-Language.
    $upbox_kein_browser = empty($_SERVER['HTTP_REFERER'])
        && empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])
        && empty($_SERVER['HTTP_SEC_FETCH_MODE']);

    if ($upbox_crawler || $upbox_kein_browser) {
        // 429 statt 403: "gerade nicht" statt "nie wieder".
        // 403 wuerde die URL bei serioesen Crawlern dauerhaft verbrennen.
        http_response_code(429);
        header('Retry-After: 3600');
        header('X-Robots-Tag: noindex');
        exit;
    }
}

unset($upbox_uri, $upbox_pfad, $upbox_asset, $upbox_tiefe, $upbox_query,
      $upbox_ua, $upbox_crawler, $upbox_kein_browser);
// UPBOX END

Was der Block tut: Er prüft, ob die URL gestapelte Filter enthält (doppelter Unterstrich oder klassische Parameter). Nur dann wird der User-Agent gegen eine Liste bekannter kommerzieller Crawler geprüft. Trifft beides zu, gibt es 429 Too Many Requests mit Retry-After: 3600 - nicht 403 Forbidden, weil 429 „gerade nicht" heißt und seriöse Crawler daraufhin drosseln, statt die URL dauerhaft zu verwerfen.

Was er nicht tut: Er hält nichts fern. PHP startet, der Worker ist belegt, die Prüfung läuft - erst dann kommt die Abweisung. Gemessen: 0,11 Sekunden für eine 429-Antwort statt 0,59 Sekunden für eine gerenderte Filterseite. Gespart wird die Datenbanklast, nicht der Worker-Slot. Gegen einen vollen Pool hilft nur eine Begrenzung vor dem Server.

Was man vor dem Einsetzen prüfen sollte: OPcache verzögert die Wirkung - nach dem Hochladen einige Minuten warten. Die .htaccess als Verstärkung weist Requests vor PHP ab, wird aber bei Shop-Updates überschrieben und muss neu eingefügt werden.

Eine begründete Reihenfolge

Wenn es gerade brennt:

  1. SAVE_BOT_SESSION = 1 in config.JTL-Shop.ini.php - eine Zeile, verhindert Session-Flut durch erkannte Bots.
  2. ObjectCache im Backend aktivieren (System → Cache - standardmäßig deaktiviert).
  3. Trefferzahlen bei Merkmalfiltern abschalten (Darstellung → Standardansichten → Artikelübersicht - JTL nennt das selbst „performancelastig").
  4. Den Code-Block oben einsetzen.

Dauerhaft: 5. Filter ab Ebene 2 nicht mehr als <a href> verlinken - per Template. Was nicht verlinkt ist, wird nicht gecrawlt. 6. robots.txt mit Mustern für Filter-URLs ergänzen. 7. noindex-Meta auf Filterseiten per Template.

Woran man merkt, dass es gewirkt hat: An der Zahl der 429-Antworten im Zugriffsprotokoll. An der PHP-FPM-Auslastung. An den 504ern - sie verschwinden. Die Gesamtzahl der Requests bleibt hoch, das ist kein Maß.

Die Frage, die keine technische ist

GPTBot, ClaudeBot und Amazonbot zu sperren heißt: in KI-Antworten nicht mehr vorkommen. Für einen Händler kann das richtig sein - aber es ist eine Geschäftsentscheidung, die als Serverproblem verkleidet daherkommt.

Sauber zu trennen: Crawler, die Trainingsdaten sammeln (GPTBot, CCBot, Google-Extended), gegenüber Crawlern, die gerade eine Live-Frage eines Nutzers beantworten (OAI-SearchBot, Google AI Overviews über den regulären Googlebot, Bing Copilot über Bingbot). Das Zweite auszusperren heißt, in KI-Antworten nicht mehr aufzutauchen, wenn ein Kunde gerade sucht. Im Code-Block oben sind KI-Crawler deshalb auskommentiert - wer sie sperren will, entfernt die Kommentarzeichen bewusst.

Häufige Fragen

An der Kennzahl Requests je Besuch. Echte Kunden liegen bei rund 5 - in zwei unabhängig gemessenen Shops dasselbe. Alles über 20 ist verdächtig, über 100 eindeutig automatisiert. Wenn Ihr Shop plötzlich 200.000 Anfragen pro Tag hat, aber die Bestellungen nicht steigen, ist es kein Kundenplus.

Kurzfristig ja - mehr PHP-Worker halten länger durch. Aber das Volumen wächst weiter. Ein größerer Server verschiebt die Grenze, er löst nicht die Ursache. Im gemessenen Shop wuchs die Last in 16 Monaten um das 69-Fache. Keine Server-Vergrößerung hält das dauerhaft Schritt.

Nicht, wenn Suchmaschinen sicher erkannt werden. Der Code-Block oben weist nur Bots auf Filter-URLs ab, nicht auf Produkt- und Kategorieseiten. Googlebot hat dort nichts verloren - Google selbst empfiehlt, Filter-URLs gar nicht erst crawlen zu lassen. Wer auf Nummer sicher gehen will: Googlebot per Reverse-DNS verifizieren (Googles eigene Anleitung), nie blockieren.

robots.txt funktioniert nur bei Crawlern, die sich daran halten - Google und Bing ja, viele KI-Crawler und getarnte Bots nein. Im gemessenen Shop geben sich nur 10,8 Prozent des Verkehrs als Bot zu erkennen. Der Rest ignoriert robots.txt oder behauptet, ein Browser zu sein. robots.txt ist Hygiene, keine Abwehr.

Das hängt von der Ausgangslage ab. Wer nur Webspace hat (Standard-Hosting, kein Root-Zugriff), bekommt mit dem Code-Block und den Backend-Einstellungen eine Entlastung - gegen das Mengenproblem ist damit aber nicht alles möglich. Wer Root-Zugriff hat, kann nginx-Ratenbegrenzung und GeoIP-Sperren zusätzlich einsetzen. Der Umfang ist unterschiedlich, der Festpreis wird im Erstgespräch genannt.

Ja - der Block oben ist kommentiert und zum Übernehmen gedacht. Er gehört in includes/config.JTL-Shop.ini.php, die bei Shop-Updates nicht überschrieben wird. Lesen Sie die Kommentare, bevor Sie ihn einsetzen. Wenn Sie unsicher sind: Wir richten das im Rahmen eines Festpreis-Projekts ein.

Nächster Schritt

"Shop-Last analysieren lassen?"

"Wenn Ihr JTL-Shop langsamer wird oder 504er auftreten: Wir schauen uns Ihre Zugriffsprotokolle an, identifizieren das Muster und sagen Ihnen, welches der beiden Probleme Sie haben - und was dagegen hilft. Festpreis, den wir im Erstgespräch nennen."

30-Minuten-Gespräch vereinbaren - kostenlos, unverbindlich →

Stand: August 2026