Tags

#Web & Publishing

Alles rund um Websites, Publishing, CMS, Blogging und den technischen Unterbau des Webs.

Ich habe einen Kirby-Kurs geschrieben

https://maurice-renck.de/de/blog/2026/i-wrote-a-kirby-course

Bots, Prewarming und schlechte Queries

Bots, Prewarming und schlechte Queries

Und wieder melde ich mich gut gelaunt und überhaupt nicht gefrustet aus dem Maschinenraum. Heute: Wie meine site()->index()-Abfragen meine Seite fast gekillt hätten. Und ich wie immer selbst daran schuld gewesen bin.

Aber von vorne.

Vielleicht war es keine gute Idee, an ein, zwei Abenden bei Trakt nachzupflegen, welche Serien ich alles schon gesehen habe. Denn das hat mich auf Ideen gebracht. Zum Beispiel: Ich könnte ja dann auch gleich alle Serien und alle Filme auf gesonderten Seiten ausgeben. Und bei Serien könnte ich ja auch noch, einfach weil es so schön ordentlich ist, die Staffeln sortieren und den Serien zuordnen.

Und wenn ich schon dabei bin: Das Ganze könnte ich doch langsam über APIs aufbauen. Klar, die Watchdaten sind nur so halb akkurat, weil ich erst ab diesem Zeitpunkt angefangen habe, Serien sauber zu tracken. Aber ganz ehrlich: Ein bisschen Unschärfe ist immer noch besser als gar keine Daten.

Und wenn ich dann schon ungefähre Watchdaten habe, kann ich ja auch direkt Watchlog-Einträge erzeugen. Wer weiß, wofür die noch gut sind.

Die Konsequenz? Plötzlich hatte meine Seite über 8.000 Watchlog-Einträge. Und über 8.126 Episoden und Filme. Mit einer Watchdauer von sage und schreibe 8,5 Monaten! Aber darum soll es hier gar nicht gehen. Manche Statistiken sollte man vielleicht einfach nicht berechnen.

Worum es geht: Ich hatte plötzlich keine kleine, gemütliche Seite mehr. Sondern ein leicht zickiges Monstrum, das morgens, wenn die Botschwärme aufwachen, meinen Server zuverlässig in die Knie zwingt.

Und schuld daran war natürlich ich.

Ich habe für jede kleine Anzeige von Content einfach site()->index() benutzt. Bedeutet: Immer erst einmal die komplette Website laden, alles durchscannen, tausende Seitenobjekte bauen und dann 99,9 Prozent davon wieder wegwerfen. Klassisches Beispiel:

„Gib mir alle Seiten, filtere Reviews raus, sortiere nach Datum und zeig mir die neuesten fünf.“

Das funktioniert. Aber eben nur so lange, wie die Seite klein ist.

Mit wachsendem Content wurde das zum Problem. Nicht, weil Kirby schlecht ist, sondern weil ich bequem war. „Hol alles, filter später“ ist einfach, aber teuer.

Was ich jetzt stattdessen mache:

Ich scanne die Inhalte genau einmal, ziehe mir daraus nur die relevanten IDs und speichere diese als Cache. Und danach arbeite ich nur noch mit diesem vorbereiteten Datensatz. Keine globalen Scans mehr pro Request, sondern ein vorbereiteter, günstiger Zugriff.

Das habe ich inzwischen umgesetzt für:

  • Tag-Lookups
  • Film- und Serienverzeichnisse
  • Watchlog-Beziehungen
  • den Home-Feed
  • meine Stories-Rail

Das Prinzip ist immer gleich: einmal berechnen, dann cachen.

Dann kam die nächste „gute“ Idee: Prewarming. Also Seiten im Hintergrund vorladen, damit sie für euch schneller da sind. Klingt erstmal sinnvoll.

War es auch. Nur habe ich es natürlich übertrieben.

Ich habe das Prewarming als Self-Requests direkt bei normalen Seitenaufrufen eingebaut. Bedeutet: Ein Request erzeugt mehrere neue Requests auf sich selbst. Solange wenig Traffic da ist, geht das gut. Sobald aber Bots anfangen, parallel meine Seiten zu crawlen, kippt das System.

Und genau das ist passiert.

Bots wie GPTBot, AhrefsBot oder SemrushBot haben parallel angefangen, vor allem die Suche aggressiv abzuklappern. Gleichzeitig liefen meine eigenen Prewarm-Requests. Ergebnis: Alle Worker belegt, nichts geht mehr.

Deshalb habe ich jetzt zwei Dinge geändert:

Die Suche ist für Bots gesperrt
Prewarming passiert nur noch minimal, aktuell nur für die Startseite
Alles andere beobachte ich erstmal.

Die eigentliche Erkenntnis aus der ganzen Geschichte ist aber ziemlich simpel:

site()->index()ist nicht falsch, solange man es nicht übertreibt, so wie ich ich.

Wenn man es bewusst für globale Aufgaben nutzt, ist alles gut. Wenn man es aber im Frontend bei jedem Request mehrfach benutzt, während die Seite wächst und komplexer wird, dann baut man sich ziemlich zuverlässig einen Flaschenhals.

Feature complete? Von wegen.

Feature complete? Von wegen.

Ich musste innerlich lachen, als ich mich dabei erwischt habe, ernsthaft zu denken, dass meine kleine Kirby-Seite jetzt erst einmal feature-complete ist. Das war wirklich ein ernsthafter, ehrlicher Gedanke. Vollkommen unironisch.

Und trotzdem kenne ich mich ja schon auch ein bisschen und habe mich schon beim Denken über mich gewundert und deshalb die letzten Tage wieder etwas im Maschinenraum rumgeschraubt:

Ich habe jetzt meine Tags-Seite versucht zu durchhirnen und aufzubohren. Denn: Ich hasse es, Inhalte zu vertaggen. Aber: Ich finde es auch unglaublich hilfreich, wenn ich es denn mal gemacht habe, um schnell Sachen wiederzufinden.

Was ich dabei gemerkt habe: Selbst wenn es niemanden interessieren sollte, gebe ich mir bei den Bookmarks viel mehr Mühe, wenn ich die hier auf hnz.io reinhaue, als wenn ich sie bei Obsidian ablege oder in die Notiz-App paste. Die gefühlte Öffentlichkeit zwingt mich zu Struktur. Und das finde ich tatsächlich hilfreich.

Ich habe jetzt ein zweigliedriges Tag-System eingeführt. Ich wähle im Artikel einfach die Kategorie aus, Kirby zeigt mir die entsprechenden (vorher angelegten) Unterkategorien an und ich muss nur noch Häkchen setzen. Ich glaube, das bekomme ich hin.

Gleichzeitig habe ich zusammen mit Chatty (Codex mit GPT-5.4) eine Taxonomie-Seite gebaut: Jeder Tag hat jetzt (wie bei WordPress) einen Beschreibungstext und für die Suche noch Synonyme. Damit es egal ist, ob man bei mir nach llm, ki, ai oder so etwas sucht.

Diese Daten habe ich genutzt, um meine Tag-Seite aufzubohren, sodass sie für mich wirklich nützlich ist. Da steht jetzt erst einmal die neue Struktur mit Hauptkategorie und Unterkategorie.

Außerdem lasse ich dort meine Orte und Locations durchsuchbar ausgeben sowie alle Regie-Leute und Haupt-Casts von Serien und Filmen, die ich getrackt habe.

Teilweise nutze ich dafür auch einfach die Loupe-Suche, um Inhalte anzuzeigen. Also eigentlich für alles, was kein klassisches Thema oder Tag ist.

Dabei habe ich gemerkt: Ich muss da noch einmal ran und das besser auf meine Bedürfnisse zuschneiden. Und ich hoffe wirklich, dass ich es so umgebaut habe, dass auch andere gut damit klarkommen.

Denn, in aller Kürze: Ich habe viele Inhalte doppelt. Gefühlt und tatsächlich.

Wenn ich einen Film logge, wird der als Watchlog automatisiert importiert. Wenn ich dazu einen längeren Text schreiben will oder nur einen Kommentar, lege ich einen entsprechenden Post an und sage dem Artikel: Bitte zeige bei der Rezension die Watchcard an. Das hier ist zum Beispiel eine Rezension von mir mit einer zugeordneten Watchcard. Und das die entsprechende Watchcard.

Das führt dazu, dass bei einer Suche wie "Starfleet Academy" sowohl meine Rezensionen als auch die Watchcards aufgetaucht sind. Relevant sind aber eigentlich nur die Rezensionen, weil dort alles aus der Watchcard enthalten ist – plus meine mal mehr, mal weniger sinnvollen Gedanken.

Also: Watchcards ausblenden, wenn ein verknüpfter Text existiert.

Das gleiche Problem habe ich bei Tags. Wenn ich die Watchcard vertagge und später noch einen Beitrag schreibe, habe ich plötzlich doppelte Inhalte unter einem Tag: Watchcard und Rezension.

Das will ich nicht manuell lösen. Ich kenne mich. Das mache ich nicht.

Also habe ich auch hier eine Regel eingebaut: Wenn Inhalte verknüpft sind (Card + Content), werden die Tags übernommen und die Watchcard fliegt aus den Übersichten raus. Wie zum Beispiel hier. Man sieht nur noch die Rezensionen und Artikel – nicht mehr die Watchcards.

Ich muss mal schauen, ob ich mein Tag-Management GitHub-fähig bekomme oder ob das wieder viel zu speziell auf mein Hirn und dieses Projekt zugeschnitten ist.

Wen’s generell interessiert: Ich habe jetzt meine einfachen Plugins für die Sharecard, Exif-Import und AI-Text veröffentlicht.