DEV Community

Cover image for The Era of Scary Cron Syntax Is Over: Meet pboss cron
Zak R.
Zak R.

Posted on

The Era of Scary Cron Syntax Is Over: Meet pboss cron

You know the feeling. You need to run a backup script every day at 9:11am, so you open a terminal, type crontab -e, and stare at a blinking cursor waiting for you to conjure five asterisks and numbers in the correct ancient order.

11 9 * * *
Enter fullscreen mode Exit fullscreen mode

Is that minute-then-hour, or hour-then-minute? Did you just schedule this for 9:11am or for the 9th minute of every hour that happens to also be... you get the idea. You copy-paste it into an online cron parser to check your own work. You feel bad about it. We all feel bad about it.

Cron syntax is one of those things every backend developer has "learned" a dozen times and forgotten a dozen times, because there's zero semantic connection between what you type and what it means. */15 * * * * doesn't look like "every 15 minutes" — it looks like line noise that happens to work.

pboss — the Bun-powered process manager — ships a cron system that fixes this without throwing away the power of raw cron when you actually need it.

The problem with crontab -e

Standard cron has a few real, practical downsides beyond "the syntax is opaque":

  • No persistence layer of its own. It's a system-level daemon, separate from whatever's managing your app processes.
  • No visibility. Want to know when a job last ran, whether it succeeded, or when it's running next? Better go dig through /var/log or set up your own logging by hand.
  • No easy one-shot scheduling. Need something to run once, next Tuesday at 11pm, and never again? You're writing a workaround, not using cron the way it was designed.
  • Machine downtime silently eats jobs, and figuring out what got skipped is a manual, aggravating exercise.

If you're already running pboss to manage your app processes, none of this needs to be a separate problem you solve separately.

Enter human-readable schedules

Here's the same 9:11am backup job in pboss:

pboss cron run everyday@9:11 "bun /srv/backup.ts"
Enter fullscreen mode Exit fullscreen mode

Read that out loud. It says exactly what it does. No mental math, no lookup table, no "wait, is Sunday 0 or 7 in this implementation."

A few more, so you get the shape of the grammar:

# Every Sunday at 10:10am, named explicitly
pboss cron run every-sunday@10:10 "sh /srv/cleanup.sh" --name cleanup

# One-shot: fires once, at a specific date and time, then it's done
pboss cron run on-date@24-10-2026-23:10 "node migrate.js"
Enter fullscreen mode Exit fullscreen mode

The grammar covers the cases you actually hit in real projects:

You want... You write...
Every day at midnight everyday
Every day at a specific time everyday@9:11
Every N seconds every-15-seconds
Every hour, or every hour at :30 everyhour / everyhour@30
Every week on a given weekday every-sunday@10:10, everyMonday@10:10, onSunday@23:10
Every month, or a specific day of month everymonth / every-15th@10:10
Every N hours or N days every-6-hours / every-2-days@8
Once, later today or tomorrow today@23:10 / tomorrow@8:00
Once, on a specific calendar date on-date@24-10-2026-23:10

A couple of details that show this was designed by someone who's actually been burned by cron before:

  • Hour 24 rolls to the next day. everyday@24:30 means 00:30 tomorrow, so you can express "half an hour after midnight" without the off-by-one anxiety.
  • Keywords are forgiving. on-date@, onDate@, and on_date@ are all the same thing — hyphens, underscores, and camelCase are interchangeable, so you don't have to remember one exact casing convention.
  • Dates are calendar-validated. Try to schedule on-date@31-02-2026 and you get a clear rejection instead of a job that silently never fires.
  • A past today@… time gets rejected with a suggestion, not silently scheduled into a black hole.
  • Missed jobs are skipped, not queued up. If the daemon or machine was down, a recurring job just reschedules to its next real future occurrence — same behavior you'd expect from classic cron, so nothing runs in a confusing backlog burst when the box comes back up.

The escape hatch: raw cron still works

This is the part that matters most, honestly. Nobody wants a "friendly" tool that boxes you in the moment your schedule gets weird. So pboss doesn't replace cron expressions — it accepts them:

pboss cron run "*/5 * * * *" "curl -s https://example.com/ping"
Enter fullscreen mode Exit fullscreen mode

You can even go beyond standard 5-field cron with a 6-field expression, where the first field is seconds:

pboss cron run "*/10 * * * * *" "node heartbeat.js"
Enter fullscreen mode Exit fullscreen mode

So the mental model is: reach for the friendly syntax by default, and drop into raw cron only for the genuinely gnarly schedules where a plain-English phrase can't capture what you need.

Managing jobs like they're first-class citizens

Because cron jobs live in the daemon itself (persisted to ~/.pboss/cron.json, surviving reboots), you get the same kind of visibility you'd expect for a managed process:

pboss cron list
Enter fullscreen mode Exit fullscreen mode
┌────┬─────────┬─────────────┬──────────────────┬───────────────────────────┬──────┬──────┬──────────┐
│ id │ name    │ schedule    │ command          │ next run                  │ runs │ last │ status   │
├────┼─────────┼─────────────┼──────────────────┼───────────────────────────┼──────┼──────┼──────────┤
│  1 │ backup  │ everyday@9  │ bun backup.ts    │ 2026-09-07 09:00 Mon      │   14 │ ✓    │ ● online │
│  2 │ cleanup │ every-sunday│ sh cleanup.sh    │ 2026-09-13 00:00 Sun      │    3 │ ✓    │ ● online │
└────┴─────────┴─────────────┴──────────────────┴───────────────────────────┴──────┴──────┴──────────┘
Enter fullscreen mode Exit fullscreen mode

Peek at upcoming runs without waiting around:

pboss cron next backup --count 5
Enter fullscreen mode Exit fullscreen mode

Force a run right now, without touching the schedule:

pboss cron trigger backup
Enter fullscreen mode Exit fullscreen mode

And clean up when a job's done:

pboss cron remove backup
Enter fullscreen mode Exit fullscreen mode

Every run gets logged automatically to ~/.pboss/logs/cron/<name>.log, with a header (job name, schedule, working directory), the command's full combined output, and a footer with exit code and duration. That's debugging information you'd otherwise have to wire up yourself.

Declaring crons alongside your apps

If you're already using an ecosystem file to manage your processes, cron jobs slot right in next to them:

export default {
  crons: [
    {
      name: "backup",
      schedule: "everyday@2:00",
      command: "bun /srv/backup.ts",
    },
    {
      name: "report",
      schedule: "every-15th@10:10",
      command: "sh /srv/report.sh",
    },
    {
      // paused until you're ready
      name: "maintenance",
      schedule: "every-sunday@5:00",
      command: "sh /srv/maintenance.sh",
      enabled: false,
    },
  ],
  apps: [
    /* … */
  ],
};
Enter fullscreen mode Exit fullscreen mode

Re-running the ecosystem file updates schedules in place — jobs are matched by name, so you can tweak a schedule and redeploy without duplicating jobs.

Or drive it all from code

import { pboss } from "pboss";

const job = await pboss.cronAdd("everyday@9:11", "bun backup.ts", { name: "backup" });

for (const j of await pboss.cronJobs()) {
  console.log(`${j.name}${j.description} (runs: ${j.runCount})`);
}

await pboss.cronTrigger("backup");   // run now
await pboss.cronRemove("backup");    // remove
Enter fullscreen mode Exit fullscreen mode

Under the hood

Jobs execute through the system shell (/bin/sh -c on Unix, cmd /c on Windows), so pipes and redirects behave exactly like you'd expect:

pboss cron run everyday@3 "bun report.ts | mail -s 'daily report' ops@example.com"
Enter fullscreen mode Exit fullscreen mode

And the scheduler itself isn't naively polling every minute and hoping — it sleeps until the next actual scheduled run with a periodic watchdog rescan, so timing stays accurate to the second even across clock adjustments.

The takeaway

Cron syntax isn't going anywhere — it's load-bearing infrastructure for the entire internet, and pboss doesn't pretend otherwise; raw expressions are still a first-class option. But for the 90% of scheduling you actually do — "run this every day," "run this every Sunday morning," "run this once, next Tuesday" — there's no reason to keep translating your intent into five cryptic fields by hand.

pboss cron run everyday@9:11 "bun /srv/backup.ts"
Enter fullscreen mode Exit fullscreen mode

That's it. That's the whole horror story, and it has a happy ending.


Want to try it: check the cron docs.

Top comments (0)