Scheduled Jobs (Crons)
Run jobs on a recurring schedule. Powered by pg_cron. The Core manages scheduling, overlap detection, and delivery to your worker.
How It Works
When you create a cron, the Core registers it with pg_cron inside PostgreSQL. On each tick, pg_cron enqueues a job into the same pgmq queue used by one-shot jobs. The scheduler picks it up and dispatches it to your worker's onJob handler.
Your worker does not need to know whether a job came from a cron or a manual enqueue. The payload tells it what to do.
Schedule Syntax
Two formats are supported:
Standard cron: 5 fields (minute hour day-of-month month day-of-week)
* * * * * # every minute
*/5 * * * * # every 5 minutes
0 9 * * * # daily at 9 AM
0 0 * * 1-5 # midnight on weekdays
0 12 $ * * # noon on the last day of each month
Seconds interval: for sub-minute scheduling (1-59)
10 seconds # every 10 seconds
30 seconds # every 30 seconds
All times are GMT unless you pass a timezone parameter.
Overlap Policy
Controls what happens when a cron fires but the previous job is still in the queue.
| Policy | Behavior |
|---|---|
skip (default) |
Do not enqueue. Prevents pile-up. |
queue |
Enqueue regardless. Jobs may stack up. |
Create a Cron From Your Frontend
import { useCrons } from "@rootcx/sdk";
const { create, update, remove, trigger } = useCrons("myapp");
// Schedule a daily check at 9 AM
await create({
name: "daily-check",
schedule: "0 9 * * *",
payload: { task: "check_replies" },
});
// Pause it
await update(cronId, { enabled: false });
// Fire it right now (for testing)
await trigger(cronId);
See useCrons for the full hook API.
Handle Cron Jobs in Your Backend
Cron jobs arrive in the onJob handler, the same as regular jobs. The payload contains everything you set at creation time plus a cron_id field added by the Core.
serve({
onJob: async (payload) => {
if (payload.task === "check_replies") {
log.info("Checking replies...");
// your logic here
return { checked: true };
}
},
});
Return a value to mark the job as completed. Throw to mark it as failed.
REST API
POST /api/v1/apps/{appId}/crons
{
"name": "daily-check",
"schedule": "0 9 * * *",
"payload": { "task": "check_replies" },
"overlapPolicy": "skip"
}
Returns a CronSchedule object with id, enabled, pgJobId, and timestamps.
See the REST API Reference for all endpoints.