
Sechzig Container auf einem Server
Eine Bare-Metal-Box führt Dutzende bis Hunderte von Hoody-Containern aus. KSM und BTRFS-Dedup machen die Marginalkosten nahezu null.
Jede Nacht um 1 Uhr curlt ein Cron-Eintrag eine Exec-URL. Das Skript führt dein Rollup-SQL auf der SQLite-URL aus und schreibt die Daily-Tabelle zurück. Kein Airflow-Postgres, kein DAG-File, kein Scheduler-Dashboard mit 14 Widgets, kein On-Call für den Orchestrator selbst.
SELECT date_trunc('day', created_at) AS d,
count(*) AS n
FROM events
WHERE created_at >= 'today'
GROUP BY 1 -- the whole pipelineDAS DASHBOARD IST DER ORCHESTRATOR. EINE URL. EIN SCHEDULE.
Die ganze Pipeline ist ein Cron-Eintrag, der auf eine Exec-URL zeigt. Der Cron-Eintrag ist ein POST an /users/root/entries. Die Exec-URL ist ein kleines Skript, das die SQLite-URL öffnet, das Rollup-SQL ausführt und die neuen Zeilen zurückgibt. Das ist der gesamte DAG.
// jede Nacht um 01:00 UTC
POST /users/root/entries
{
"schedule": "0 1 * * *",
"command": "curl -fsS https://exec.containers.hoody.com/scripts/rollup/run"
}// der gesamte Pipeline-Body
import { Database } from "bun:sqlite";
const db = new Database("events.db");
db.run(`INSERT INTO rollup_daily
SELECT date_trunc('day', created_at), count(*)
FROM events GROUP BY 1;`);
return { ok: true, rows: db.query("SELECT * FROM rollup_daily").all() };Wenn das Rollup scheitert, sagen es die Cron-Logs. Wenn du gestern backfillen musst, curlst du die Exec-URL von Hand mit einem Date-Parameter. Es gibt kein zweites System zu lernen, keine Scheduler-Datenbank am Leben zu halten, kein DAG-File zu committen. Der Orchestrator ist ein Cron-Eintrag, der auf eine URL zeigt.
Das Hoody Kit liefert den Scheduler, die Runtime und das Storage als ganz normale HTTP-Services. Die Pipeline ist der curl-Call zwischen ihnen — sonst nichts.
hoody-cron speichert Schedules als Ressourcen unter /users/root/entries. Keine Postgres-Metadaten-DB zum Backuppen, kein Scheduler-Container, der gesund bleiben muss, kein DAG-Repository zum Deployen. POSTe eine Zeile, und der Run feuert.
hoody-exec führt das Rollup-Skript on-demand unter exec.containers.hoody.com/scripts/rollup/run aus. cron curlt es, kriegt 200, loggt die Antwort. Keine Worker-Queue, kein Broker, kein gepickelter Task-Graph.
Jeder Exec-Call gibt die neuen Zeilen als JSON zurück und wird von cron mit Status, Timestamp und stdout geloggt. Backfills, Failures und Reruns leben alle in denselben zwei URLs — nichts Extras zu einem Log-Aggregator zu shippen.
Die Pipeline sind zwei URLs und ein Date-Param. Gestern erneut laufen zu lassen ist dieselbe Form wie der nächtliche Run, nur mit ?date=2026-04-30 an der Exec-URL. Kein Replay-UI, keine Scheduler-Eigenheiten.
Wenn der 1-Uhr-Run einen Non-2xx zurückgegeben hat, zeigt der Last-Run-Record des Eintrags auf hoody-cron den Exit-Code und den eingefangenen Response-Body. Kein separater Alerting-Service zu verdrahten — GET den Eintrag und lies.
Das Skript akzeptiert einen Date-Parameter. Reich gestriges Datum durch, und es berechnet die Rollup-Zeile dieses Tages neu — ersetzt die kaputte mit einem INSERT OR REPLACE. Ein Befehl, kein DAG-Re-Trigger-UI.
exec gibt die frisch geschriebene Rollup-Zeile als JSON zurück. Diff sie gegen das, was du erwartet hast, und mach weiter. Sonst nichts zu prüfen — die Dashboard-URL serviert dieselbe Tabelle, die du gerade geschrieben hast.
Drei Zahlen beschreiben das gesamte System. Vergleich sie mit dem, was ein Airflow-Deployment heute in deinem Repo aussieht.
minute, hour, day-of-month, month, day-of-week. Das ist die volle Konfigurationsoberfläche dafür, wann ein Run feuert.
ein POST, um den Schedule zu registrieren, ein GET, der das Skript ausführt. Das ist die gesamte deploybare Pipeline.
kein Scheduler-Prozess am Leben zu halten, keine Metadaten-Datenbank, kein Worker-Pool. Hoody Kit hält die Schedules und führt das Skript aus.
Die Zahlen beschreiben das Cron-+-Exec-Modell auf Hoody Kit. Deine bestehende Pipeline hat wahrscheinlich mehr bewegliche Teile; das ist der Punkt des Vergleichs.
Der Orchestrator ist ein Cron-Eintrag, der auf eine URL zeigt.
Die Orchestrierungsschicht kollabiert in einen einzeiligen Cron. Der DAG lebt in deinem Skript.
Hör auf, einen Orchestrator zu betreiben. Lass einen Cron-Eintrag laufen.