
Soixante conteneurs sur un seul serveur
Une machine bare-metal exécute des dizaines à des centaines de conteneurs Hoody. La dédupplication KSM et BTRFS rend le coût marginal quasi nul.
Pointez votre vrai webhook Stripe vers une URL hoody-files pendant trente minutes. Le répertoire contient maintenant quatorze fichiers JSON — chaque payload qui a frappé la production, octet pour octet. Une seule entrée cron exécute un script exec qui les renvoie en POST sur la staging à 9h, du lundi au vendredi. La planification expire samedi prochain et se supprime elle-même.
{ "id": "evt_3OHk8ZJs2k9aXq1vQ", "type": "payment_intent.succeeded", "created": 1714723522, "data": { "object": { "id": "pi_3OHk8ZJs2k9aXq1v0K7rT4mB", "amount": 4900, "currency": "usd", "status": "succeeded" } } }
capturé par votre vrai webhook · rejoué par une seule entrée cron
Tout le flux tient en trois URLs. Le trafic de production arrive sur l'URL de capture. Les fichiers atterrissent dans hoody-files. Cron parcourt le dossier et POSTe les corps vers la staging. Pas de broker, pas de file d'attente, pas de service de replay — seulement un répertoire et une planification.
Réglez l'URL de votre webhook Stripe / Intercom / GitHub vers un chemin hoody-files. Chaque événement arrive sous forme de PUT et atterrit comme un fichier JSON nommé avec son horodatage. Le répertoire est l'enregistrement.
Les fichiers persistent sur disque ; chaque fichier a sa propre URL. Parcourez le répertoire dans un navigateur, listez-le via l'API, ou connectez-vous en shell avec curl. L'enregistrement est un fait que vous pouvez cat, scp ou versionner.
POSTez une entrée cron managée avec la planification 0 9 * * 1-5 et la commande bash /scripts/replay.sh /webhooks/2026-05-03. Le script liste le répertoire et POSTe chaque fichier vers la staging dans l'ordre des horodatages.
Capture et replay sont le même protocole sur des jours différents. La chose qui a enregistré les octets est la chose qui les rejoue. Pas de parseur JSONL, pas de sidecar, pas de format d'enregistrement à apprendre — des fichiers dans un dossier, dans l'ordre temporel.
La capture, c'est un PUT par événement webhook. Le replay, c'est un POST vers l'API cron. Hoody Files détient l'enregistrement ; Hoody Cron le parcourt sur planification ; hoody-exec exécute le script bash qui fait les POSTs. Trois services, aucune glu entre eux.
# point your real webhook at hoody-files curl -X PUT \ https://files.containers.hoody.com/webhooks/2026-05-03/stripe-08-15-22.json \ --data-binary @- # 30 minutes later, the directory holds 14 files HTTP/1.1 201 Created webhooks/2026-05-03/stripe-08-15-22.json
# one cron entry replays the morning at 9am, mon-fri curl -X POST \ https://cron.containers.hoody.com/api/v1/cron/users/me/entries \ -d '["schedule":"0 9 * * 1-5","command":"bash /scripts/replay.sh /webhooks/2026-05-03","expires_at":"2026-05-10T09:00:00Z"]' HTTP/1.1 201 Created { "id":"f0a8", "schedule":"0 9 * * 1-5", "expires_at":"2026-05-10T09:00:00Z" }
Le côté capture tourne une fois un vendredi matin. Le côté replay tourne chaque jour ouvré jusqu'à samedi prochain, où le champ expires_at de l'entrée cron supprime la planification. Vous avez écrit une URL PUT dans la config de votre webhook, et un POST dans l'API cron — c'est tout le test de charge.
Le trafic synthétique est ce que vous imaginiez que la requête ressemblait. Le trafic capturé est ce qui est réellement arrivé. Mêmes noms de champs, mêmes cas limites, mêmes surprises.
L'enregistrement capture le JSON exact que Stripe a envoyé — y compris chaque champ nullable, chaque type d'événement inattendu, chaque format customer_id que vous avez oublié. Votre handler rencontre les mêmes payloads sur lesquels il a échoué hier.
L'expression cron 0 9 * * 1-5 fait atterrir le replay à l'heure où vos vrais utilisateurs utilisent réellement le système. Le handler testé voit l'affluence du matin contre les mêmes caches, les mêmes voisins cron, la même base de données bruyante.
Le dossier est immuable ; le cron tourne chaque jour ouvré jusqu'à expires_at. Si le handler casse encore lors du run de mardi, vous le réparez et laissez celui de mercredi le prouver. Même entrée à chaque fois — le handler est la seule chose qui change.
Les chiffres viennent de l'API des entrées managées Hoody Cron et de la spec d'expression cron standard — pas de benchmarks inventés.
Expression cron standard à 5 champs — minute, heure, jour-du-mois, mois, jour-de-la-semaine. La même syntaxe que vous utilisiez en 1985 planifie encore le replay en 2026.
GET /users/[user]/entries pagine jusqu'à 200 entrées managées à la fois. Soixante-trois planifications de replay par environnement reste largement dans le budget.
Créez le replay récurrent avec un seul POST /users/me/entries — schedule, command, expires_at. PATCH plus tard pour le mettre en sourdine ; DELETE pour le retirer ; expires_at le retire pour vous.
Limites selon l'API Hoody Cron Managed Entries : expressions cron standard à 5 champs plus les macros @daily / @hourly, pagination jusqu'à 200 entrées par page, expires_at est optionnel et désactive automatiquement l'entrée passée la deadline.
Trafic de production, enregistré une fois, rejoué sur planification.
Les outils standards pour rejouer le trafic webhook — enregistreurs, services de replay, mocks planifiés. Chacun est un SaaS, un sidecar ou un script à materner. La paire hoody-files + hoody-cron n'est rien de tout cela.
Capturez le trafic de vendredi. Planifiez le replay de la semaine prochaine. Laissez l'entrée cron expirer d'elle-même quand l'expérience est terminée.