Hintergrundjobs in einer Web-App ausführen: Queues, Scheduler und Cron
Um Hintergrundjobs in einer Web-App auszuführen, teilst du die Arbeit zuerst in zwei Arten. Ausgelöste Jobs (eine Willkommens-E-Mail senden, einen Upload verarbeiten) lassen sich in einer Job-Queue speichern, oft einer Tabelle in deiner Datenbank, und von einem Worker mit Wiederholungen abarbeiten. Geplante Jobs (ein nächtlicher Bericht, Erinnerungen alle 15 Minuten) brauchen etwas, das nach einem Zeitplan auslöst: die Cron-Funktion eines Hosts oder einen externen Scheduler, der einen geschützten Endpunkt in deiner App aufruft. Mache Jobs immer so, dass sie zweimal laufen dürfen, protokolliere Fehler und verlasse dich nie auf einen Timer in einem Server, der schlafen oder neu starten kann.
Dieser Leitfaden erklärt die Optionen, wann welche passt und wie du sie mit einem KI-App-Builder einrichtest, auch auf Hosts, die auf null skalieren.
Was als Hintergrundjob gilt
Alles, was langsam oder unzuverlässig ist oder für die sofortige Antwort an den Nutzer nicht gebraucht wird:
- E-Mails, Benachrichtigungen und Belege versenden
- Bilder verkleinern, Videos umwandeln, PDFs erzeugen
- Langsame APIs von Drittanbietern aufrufen, einschließlich KI-Modelle für lange Aufgaben
- Daten aus einem anderen System importieren oder synchronisieren
- Nächtliche Bereinigung, Berichte und Erinnerungen
Macht man das innerhalb der Anfrage, werden Seiten langsam und fragil: Ist der E-Mail-Anbieter gerade nicht erreichbar, schlägt die Anmeldung des Nutzers fehl. Verschiebt man es in den Hintergrund, bekommt der Nutzer eine sofortige Antwort, und der Job lässt sich bei Bedarf wiederholen.
Die Optionen
| Option | So funktioniert sie | Vorteile | Nachteile |
|---|---|---|---|
| Fire-and-forget im selben Prozess | Antworten, dann die Arbeit im Server weiterführen | Keine Einrichtung | Geht verloren, wenn der Server stoppt; keine Wiederholungen |
Timer im Prozess (setInterval, setTimeout) | Ein Timer im laufenden Server | Trivial | Läuft nicht, während er schläft; doppelt bei mehreren Kopien |
| Datenbankbasierte Queue | Jobs als Zeilen gespeichert; ein Worker holt und führt sie aus | Nutzt die Datenbank, die du schon hast; dauerhaft; leicht zu prüfen | Du baust Wiederholungen und Sperren selbst; etwas muss den Worker starten |
| Eigene Queue (Redis-basiert oder gemanagt) | Ein Queue-Dienst plus Worker | Ausgereifte Wiederholungs- und Planungsfunktionen | Ein weiterer Dienst, der betrieben und bezahlt werden muss |
| Gehosteter Job- oder Workflow-Dienst | Ein Drittanbieter ruft deine Endpunkte mit Wiederholungen und Zeitplänen auf | Planung und Wiederholungen übernimmt er für dich | Abhängigkeit vom Anbieter; ein weiteres Konto und ein weiterer Schlüssel |
| Externer Scheduler, der einen Endpunkt aufruft | Ein Timer irgendwo anders sendet nach Zeitplan eine HTTP-Anfrage | Funktioniert auf jedem Host, auch bei Skalierung auf null | Mindestintervalle und Verzögerungen; den Endpunkt schützen |
| Cron des Hosts | Die Plattform führt zeitgesteuert einen Befehl aus | Einfach, wo es ihn gibt | Nicht jeder Host bietet ihn |
Es gibt keine einzig richtige Antwort. Eine kleine App braucht oft nur eine Datenbank-Queue plus einen externen Scheduler.
Warum Hosts, die auf null skalieren, die Lage verändern
Viele moderne Hosts schicken deine App schlafen, wenn niemand sie nutzt, und wecken sie bei der nächsten Anfrage. Das spart Geld, aber ein schlafender Server führt keinen Code aus: Timer laufen nicht, Worker fragen nicht ab. Auf solchen Hosts muss geplante Arbeit mit einer eingehenden Anfrage beginnen, und die einfachste Quelle dafür ist ein externer Scheduler. Jeder Aufruf weckt die App (und oft auch ihre Datenbank), also kostet ein Aufruf jede Minute mehr als einer alle 15 Minuten. Wähle den langsamsten Zeitplan, der den Bedarf erfüllt.
Muster 1: eine Datenbank-Job-Queue
Für ausgelöste Jobs:
- Lege eine Tabelle
jobsan: Typ, Payload (JSON), Status (pending,running,done,failed), Versuche, run_after, last_error, Zeitstempel. - Wenn etwas passiert, füge eine Job-Zeile in derselben Transaktion ein wie die Änderung, die sie ausgelöst hat, damit beide zusammen gelingen oder scheitern.
- Ein Worker holt fällige Jobs, setzt sie auf
running, erledigt die Arbeit und setzt sie aufdone. - Bei einem Fehler erhöhst du
attempts, setztrun_afterspäter (zum Beispiel nach 1, 5, dann 30 Minuten) und speicherst den Fehler. Nach einem Maximum markierst du den Job alsfailedund alarmierst jemanden.
Können mehrere Worker gleichzeitig laufen, müssen Jobs sicher beansprucht werden. Bei Postgres lässt SELECT ... FOR UPDATE SKIP LOCKED jeden Worker andere Zeilen beanspruchen, ohne dass es zu Kollisionen kommt.
Was startet den Worker? Auf einem immer laufenden Server eine Schleife in einem eigenen Prozess. Auf einem Host, der auf null skaliert, kann der geplante Endpunkt aus Muster 2 bei jedem Aufruf einen Stapel fälliger Jobs abarbeiten.
Muster 2: ein externer Scheduler, der deine App aufruft
Für geplante Jobs:
- Füge einen Endpunkt hinzu, etwa
POST /api/cron/send-reminders. - Schütze ihn: Verlange ein geheimes Token im Header, das auf beiden Seiten als Geheimnis hinterlegt ist, und lehne alles andere ab.
- Mache ihn idempotent: Läuft er zweimal in derselben Minute, dürfen keine zwei Erinnerungen verschickt werden. Halte fest, was verschickt wurde.
- Halte jeden Aufruf kurz: Verarbeite einen Stapel (sagen wir 100 Elemente) und lass den nächsten Aufruf den Rest übernehmen.
- Richte einen Scheduler darauf aus.
Optionen für den Scheduler:
- Geplante GitHub-Actions-Workflows. Kostenlos innerhalb der Nutzungslimits von GitHub. Laut den Dokumenten von GitHub liegt das kürzeste Intervall (Stand September 2026) bei einmal alle 5 Minuten. Läufe können zu Stoßzeiten verzögert werden, besonders zu Beginn jeder Stunde. Zeitpläne verwenden standardmäßig UTC. Geplante Workflows in einem öffentlichen Repository werden nach 60 Tagen ohne Aktivität im Repository deaktiviert.
- Gehostete Cron-Dienste. Es gibt viele Dienste, deren einzige Aufgabe ist, eine URL nach Zeitplan aufzurufen. Prüfe Zuverlässigkeit, Mindestintervall und Benachrichtigungen, bevor du dich darauf verlässt.
- Der Scheduler deines Cloud-Anbieters. Wenn du bereits einen großen Cloud-Anbieter nutzt, hat er einen verwalteten Scheduler, der einen HTTPS-Endpunkt aufrufen kann.
- Ein gehosteter Job- oder Workflow-Dienst. Diese vereinen Planung, Queues und Wiederholungen und rufen für jeden Schritt deine Endpunkte auf. Vergleiche Preise und Limits auf der Website jedes Anbieters.
Muster 3: den Anbieter das erledigen lassen
Manchmal ist der beste Hintergrundjob gar keiner:
- Zahlungen. Stripe wiederholt fehlgeschlagene Abo-Zahlungen und sendet Webhooks. Du reagierst, statt abzufragen. Siehe was ein Webhook ist.
- E-Mail. Anbieter stellen den Versand in eine Queue und wiederholen ihn, sobald du die Nachricht übergeben hast.
- Massenweise KI-Arbeit. OpenAI und Anthropic bieten Batch-APIs für nicht eilige Anfragen, die du einreichst und später abholst.
Prompts für deinen KI-Builder
Für eine Queue:
Füge eine Hintergrund-Job-Queue hinzu, mit einer Tabelle jobs in unserer Datenbank (Typ, Payload als JSON, Status, Versuche, run_after, last_error). Wenn sich ein Nutzer anmeldet, füge in derselben Transaktion einen Job send_welcome_email ein, statt inline zu senden. Füge eine Funktion processJobs(limit) hinzu, die fällige Jobs mit SELECT ... FOR UPDATE SKIP LOCKED beansprucht, sie ausführt und Fehler nach 1, 5 und 30 Minuten erneut versucht. Nach 4 Versuchen wird der Job als failed markiert.
Für einen geplanten Auslöser:
Füge POST /api/cron/tick hinzu, geschützt durch ein Bearer-Token aus dem Geheimnis CRON_SECRET. Lehne jede Anfrage ohne Token ab. Jeder Aufruf führt processJobs(100) aus und sendet Buchungserinnerungen, die in den nächsten 24 Stunden fällig sind und noch nicht gesendet wurden. Gesendete Erinnerungen werden festgehalten, damit nichts zweimal verschickt wird. Gib eine JSON-Zusammenfassung dessen zurück, was gelaufen ist. Schreibe dann einen GitHub-Actions-Workflow, der diesen Endpunkt alle 15 Minuten aufruft und URL und Token aus den Repository-Geheimnissen liest.
Häufige Fehler
- Sich auf
setIntervalverlassen. Es stoppt stillschweigend, wenn der Server schlafen geht oder neu startet, und verdoppelt sich, wenn zwei Kopien laufen. - Ein ungeschützter Cron-Endpunkt. Jeder, der ihn findet, kann deine Jobs auslösen oder deine E-Mail-Rechnung hochtreiben.
- Jobs, die nicht idempotent sind. Wiederholungen und doppelte Scheduler-Aufrufe werden passieren. Entwirf dafür.
- Keine Sichtbarkeit bei Fehlern. Ein Job, der eine Woche lang still fehlschlägt, ist schlimmer als einer, der laut fehlschlägt. Protokolliere Fehler und alarmiere bei wiederholten Fehlern.
- Lange Läufe in einer einzigen Anfrage. Anfragen laufen in ein Timeout. Verarbeite in Stapeln.
- Zu oft planen. Jeder Aufruf auf einem Host, der auf null skaliert, weckt die App und kostet Geld. Passe das Intervall dem echten Bedarf an.
- Zeitzonen. „9 Uhr“ bedeutet für deinen Scheduler (oft UTC) und für deine Nutzer etwas anderes. Speichere Zeiten in UTC und rechne sie pro Nutzer um.
- Geheimnisse in der Workflow-Datei. Bewahre Token im Geheimnisspeicher des Schedulers auf. Siehe wie du API-Schlüssel sicher aufbewahrst.
Checkliste
- Langsame Arbeit ist aus Nutzeranfragen herausgelöst
- Jobs sind dauerhaft gespeichert, nicht nur im Speicher
- Wiederholungen mit wachsenden Pausen und einem Maximum
- Jeder Job darf zweimal laufen
- Geplanter Endpunkt ist durch ein geheimes Token geschützt
- Jeder Lauf verarbeitet einen begrenzten Stapel
- Fehlgeschlagene Jobs sind sichtbar, mit Alarmen
- Das Intervall ist unter Berücksichtigung der Hosting-Kosten gewählt
- Zeiten sind in UTC gespeichert
Hintergrundjobs in Mythex
Die Dokumentation von Mythex beschreibt keine geplanten oder Cron-Jobs. Veröffentlichte Apps und ihre Datenbanken schlafen, wenn sie inaktiv sind, und wachen bei der nächsten Anfrage auf (siehe Hosting-Limits). Verlass dich also nicht auf Timer in deiner App. Der funktionierende Weg ist der oben beschriebene: Bitte den Agenten um eine Jobs-Tabelle und einen token-geschützten Endpunkt und richte dann einen externen Scheduler auf deine veröffentlichte URL. Speichere das Token als Projektgeheimnis und denke daran, dass jedes Aufwachen Credits für die Zeit verbraucht, in der App und Datenbank wach sind. Wähle deshalb ein sinnvolles Intervall. Braucht deine App dafür ein API-Backend, ist das REST-API-Backend-Rezept ein Ausgangspunkt, und wie du eine REST-API baust erklärt, wie du die Endpunkte entwirfst. Ist das Kernstück deines Produkts ein dauerhaft laufender Worker oder Bot, passt womöglich ein Host, der für dauerhafte Prozesse gebaut ist, besser.
Fragen
Was ist ein Hintergrundjob?
Ein Hintergrundjob ist Arbeit, die deine App außerhalb der Anfrage erledigt, auf die ein Nutzer wartet, etwa E-Mails versenden, Bilder verkleinern, Berichte erstellen oder Daten synchronisieren. Der Nutzer bekommt eine schnelle Antwort, der Job läuft separat und kann bei einem Fehler erneut versucht werden.
Wie führe ich eine geplante Aufgabe aus, wenn mein Host keinen Cron hat?
Füge einen geschützten Endpunkt hinzu, der die Arbeit erledigt, und lass einen externen Scheduler ihn nach einem Zeitplan aufrufen. Optionen sind ein geplanter GitHub-Actions-Workflow, ein gehosteter Cron-Dienst oder der Scheduler deines Cloud-Anbieters. Schütze den Endpunkt mit einem geheimen Token.
Kann ich setInterval oder setTimeout für geplante Jobs verwenden?
Nur für kleine, unwichtige Aufgaben auf einem Server, der immer läuft. Wenn der Server neu startet, auf null skaliert oder mehrere Kopien laufen, gehen Timer verloren oder laufen mehrfach. Speichere geplante Arbeit in einer Datenbank oder nutze einen Scheduler.
Unterstützt Mythex Cron-Jobs?
Die Dokumentation von Mythex beschreibt keine geplanten oder Cron-Jobs, und veröffentlichte Apps schlafen, wenn sie inaktiv sind. Der verlässliche Weg ist ein externer Scheduler, der einen geschützten Endpunkt deiner App aufruft. Dadurch wacht die App auf und führt die Arbeit aus.