
Sixty containers on one server
One bare-metal box runs dozens to hundreds of Hoody containers. KSM and BTRFS dedup make the marginal cost near zero.
Post a cron entry on Monday with expires_at set to Friday 09:00. The job pages your phone every 30 minutes for four days, then deletes itself the moment the shift ends. The next on-call posts theirs. No PagerDuty schedule, no shared scheduler config, no calendar reminder to disable it.
the entry that pages m.dossantos exists only while m.dossantos is on call
Three points in the week. The cron entry's existence tracks the shift exactly — no overlap, no gap, no leftover crontab line.
One curl with schedule */30, command pointed at hoody-notifications/push/me, and expires_at = Friday 09:00:00Z. Server returns id e7d3.
Every 30 minutes for four days the entry runs and pings hoody-notifications. Only your device. The team channel stays quiet.
At 09:00:00Z the cron service deletes e7d3. The 09:30 tick has nothing to fire. The next on-call has already posted theirs.
Each on-call writes one POST when their shift starts. The expires_at field is the entire handoff protocol — the cron service does the cleanup, on the second.
The whole rotation protocol is two HTTP calls per week. The on-call posts on Monday, lists on Friday, sees the entry is already gone. There is no shared schedule file to merge into.
# monday 09:00 — i'm on call until friday 09:00 curl -X POST \ https://oncall.containers.hoody.com/users/me/entries \ -H "Content-Type: application/json" \ -d '["schedule":"*/30 * * * *","command":"curl -fsS hoody-notifications/push/m.dossantos","comment":"on-call wk19","expires_at":"2026-05-08T09:00:00Z"]' # response HTTP/1.1 201 Created { "id":"e7d3", "expires_at":"2026-05-08T09:00:00Z", "enabled":true }
# friday 09:01 — the next on-call took over curl GET https://oncall.containers.hoody.com/users/me/entries HTTP/1.1 200 OK [ // my entry e7d3 is gone — it expired // at 09:00 sharp. j.okafor's new // entry took over at 09:00:30. ] # no slack thread, no calendar reminder
No shared scheduler service is involved. The cron entry is owned by the engineer; nothing about the next on-call's setup depends on the previous one cleaning up.
An on-call entry that owns its own lifetime stops three classes of mistakes that PagerDuty configs and calendar reminders cannot.
Because the entry's command points at your personal notify endpoint, escalations route to your phone for the duration of your shift, and only that. No accidental team-channel spam at 3am.
There is no escalation_policy.yaml that everyone touches. Each engineer owns their entry. Two on-calls in different time zones can't conflict by editing the same file.
When Friday 09:00 rolls over you don't ask 'wait, am I still getting these?' The entry is already gone. Verifying the handoff is one GET that returns one fewer row.
Numbers come from the Hoody Cron API. Real limits, not invented ones.
Auto-expiration runs against the system clock. A 09:00:00Z expires_at deletes within the same minute the cron tick fires — no 5-minute janitor lag.
Standard 5-field cron expressions plus @hourly / @daily / @weekly macros. */30 * * * * is what fires every 30 minutes during your shift.
Each system user has their own crontab. The next on-call's entry lives under their own /users/[name]/entries — never touching yours.
Limits per the Hoody Cron API: managed entries are JSON CRUD with UUIDs and expires_at; raw crontab access available per user; per-user crontab isolation is built in.
When the shift ends, so does the cron entry — automatically.
The standard reach-for-it tools when you want on-call rotations. Each one charges you a service, a config repo, and a handoff ritual. A cron entry with expires_at charges you one POST.
Stop disabling crontab lines on Friday morning. Set expires_at on Monday and forget it.