Skip to Content
AutomateCron Jobs

Cron Jobs

Cron jobs are JavaScript code snippets stored in the database and executed on a schedule using standard cron expressions. They run server-side with access to all platform services.

Database Schema

daas_cron_jobs

ColumnTypeDescription
iduuidPrimary key
nametextHuman-readable name
descriptiontextOptional description
scheduletext5-field cron expression
timezonetextIANA timezone (e.g., Asia/Singapore)
codetextJavaScript code to execute
statustextactive or inactive
timeout_msintegerMaximum execution time in ms
memory_limit_mbintegerSandbox memory limit in MB (default 64)
runningbooleanLock flag — true while executing
running_sincetimestamptzWhen the current run started
last_run_attimestamptzLast execution time
last_run_statustextrunning, success, error, or timeout
next_run_attimestamptzCalculated next run time

daas_cron_history

ColumnTypeDescription
iduuidPrimary key
job_iduuidFK → daas_cron_jobs
job_nametextJob name at time of run (denormalized)
triggered_attimestamptzWhen the job was scheduled to fire
started_attimestamptzWhen execution actually began
finished_attimestamptzWhen execution ended
duration_msintegerTotal execution time
statustextrunning, success, error, or timeout
errortextError message if failed
logstext[]Lines captured from console.log
triggered_bytextschedule, manual, or extension

Cron Expression Reference

┌───────── minute (0–59) │ ┌─────── hour (0–23) │ │ ┌───── day of month (1–31) │ │ │ ┌─── month (1–12) │ │ │ │ ┌─ day of week (0–7, 0=Sun) │ │ │ │ │ * * * * *
ExpressionMeaning
* * * * *Every minute
0 * * * *Every hour
0 0 * * *Every day at midnight
0 9 * * 1Every Monday at 9:00 AM
*/15 * * * *Every 15 minutes
0 0 1 * *First day of every month
0 6,18 * * *6 AM and 6 PM daily

Code Sandbox

Each job runs in an isolated sandbox with these globals:

AvailableNot available
context — job metadatasetTimeout / setInterval
services — platform servicesrequire / import
console.log/warn/error/infoeval
Standard JS globalsFile system access

Available services

// Items CRUD const svc = await services.items('articles'); await svc.readByQuery({ filter: { status: { _eq: 'draft' } } }); await svc.createOne({ title: 'Auto-generated' }); await svc.updateOne(id, { processed: true }); await svc.deleteOne(id); // Schema services await services.collections(); await services.fields(); await services.relations(); // Files and versions await services.files(); await services.versions(); // Send email await services.mail({ to: 'user@example.com', subject: 'Report', html: '<p>Done</p>' }); // Trigger another cron job await services.cron.trigger('job-id-or-name'); // Whitelisted environment variables const apiKey = services.env.MY_API_KEY; // Safe HTTP (domain-restricted — configure EXTENSION_ALLOWED_DOMAINS) const res = await services.fetch('https://api.example.com/data'); // Custom services const notifier = await services.custom('slack-notify'); // Raw Supabase (bypasses RLS — use with caution) const { data } = await services.supabase.from('table').select('*');

Example: Cleanup old records

// Delete items older than 30 days const cutoff = new Date(); cutoff.setDate(cutoff.getDate() - 30); const svc = await services.items('daas_activity'); const old = await svc.readByQuery({ filter: { timestamp: { _lt: cutoff.toISOString() } }, fields: ['id'], limit: 500, }); for (const row of old) { await svc.deleteOne(row.id); } console.log(`Cleaned up ${old.length} old activity records`);

REST API

MethodPathDescription
GET/api/cronList cron jobs
POST/api/cronCreate cron job
GET/api/cron/:idGet cron job
PATCH/api/cron/:idUpdate cron job
DELETE/api/cron/:idDelete cron job
POST/api/cron/:id/runTrigger job manually
POST/api/cron/:id/cloneClone a job (always created inactive)
GET/api/cron/:id/historyGet history for one job
GET/api/cron/historyGet all job history

The running lock prevents concurrent executions of the same job. If a job times out without clearing the lock, use PATCH /api/cron/:id to set running: false.

Clustered Deployments

In production the app runs as a multi-process cluster (one worker per core). The cron scheduler runs on a single leader worker, so each job fires exactly once per tick regardless of worker count; if the leader worker exits, another worker takes over scheduling. Creating, updating, activating, or deleting a job via the API takes effect immediately — the change is relayed to the leader over the cluster message bus, whichever worker served the request.

Cron console.log output is captured into the job’s history (logs), which is stored in the database and visible from any worker. The in-memory Logs page, however, only shows output from the worker serving your request — see Logs.

Last updated on