Cron Jobs
Cron Jobs
Declare recurring background jobs in VitNode plugins and execute them via internal or external cron triggers.
A cron job in VitNode consists of a named handler and a standard 5-field cron expression. Cron definitions are automatically registered in the core_cron database table and manageable through the AdminCP.
Quick start
1. Define a Cron Job
Create a cron definition in your plugin:
import { buildCron } from '@vitnode/core/api/lib/cron'
export const cleanupCron = buildCron({
name: 'cleanup-drafts',
description: 'Remove expired post drafts every midnight',
schedule: '0 0 * * *', // Standard cron syntax
handler: async (c) => {
await c.get('log').info('Running midnight cleanup...')
},
})2. Register in an API Module
Attach the cron job to a module in src/api/modules/:
import { buildModule } from '@/api/builders'
import { cleanupCron } from '../../cron/cleanup.cron'
export const postsModule = buildModule({
name: 'posts',
routes: [listPostsRoute],
cronJobs: [cleanupCron],
})When your plugin is mounted in config.api.ts, the cron job is automatically registered.
Execution Adapters
VitNode does not hold persistent timers in the HTTP worker. Instead, jobs are triggered via an adapter:
Option A: In-Process Node CRON (Single Server)
Best for single-instance or local development. Configure in vitnode.api.config.ts:
import { NodeCronAdapter } from '@vitnode/node-cron'
import { buildApiConfig } from '@vitnode/core/vitnode.config'
export const vitNodeApiConfig = buildApiConfig({
cron: NodeCronAdapter(),
})Option B: External Webhook (Multi-Instance / Serverless)
Trigger runs via external HTTP schedulers (AWS EventBridge, GitHub Actions, or crontab):
curl -X POST https://your-domain.com/api/@vitnode/core/cron -H "Authorization: Bearer $CRON_SECRET"Manage cron jobs in the Debug Panel
Open Debug Panel ā Cron & queue in the AdminCP (/admin/core/debug/cron), or type "Cron jobs" into the āK admin search. Viewing it needs the cron ā can_view staff permission.
- The table lists every job with its Name, Plugin and Time: the schedule, a status badge, and the last and next run. It is sorted by next run, with a search box to find a job.
- The play button on a row (Run Job Now) runs that job on demand. It needs the
cron ā can_runpermission.
Health warnings
Cron fails quietly by nature: nobody notices a job that didn't run. So VitNode watches for it.
A job is overdue when its next scheduled run is more than 15 minutes in the past. Never-run jobs count from the moment they were registered.
The scheduler card at the top of the section sums it up:
| What you see | What it means |
|---|---|
| Red Scheduler stopped | A job is overdue and nothing has run since. The scheduler is stopped or misconfigured, and the queue isn't draining either. |
| Amber N cron jobs are overdue | The scheduler ticks, but some jobs aren't finishing. A job that throws keeps its last successful run, so look for its error in the server logs. |
| Green All jobs on schedule | Everything ran on time. Go make a coffee. |
Next to it you get the last run, the next run and how many jobs are registered. The table below lists every job with an Overdue, On schedule or Waiting for first run status.
The same check powers the Debug Panel Overview and the Cron Jobs and Queue Tasks cards at Core ā System ā Integrations.
buildCron Options
Prop
Type