Cron Jobs — Scheduled Serverless Task Automation
Schedule any function to run automatically using cron expressions. Monitor execution history, manage job status, and trigger manual runs.
// Database Cleanup (Daily at Midnight)
Attach the db-pool layer. Schedule with 0 0 * * *.
db-cleanup.jstypescript
// Requires layer: db-pool
const db = require('db-pool');
export const handler = async (event) => {
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
const cutoff = thirtyDaysAgo.toISOString();
// Purge expired sessions
const sessions = await db.query(
'DELETE FROM sessions WHERE expires_at < $1 RETURNING id', [cutoff]
);
// Clean temp uploads
const uploads = await db.query(
'DELETE FROM temp_uploads WHERE created_at < $1 RETURNING id', [cutoff]
);
// Clean old logs
const logs = await db.query(
'DELETE FROM function_logs WHERE created_at < $1 RETURNING id', [cutoff]
);
return {
statusCode: 200,
body: {
sessionsDeleted: sessions.rowCount,
uploadsDeleted: uploads.rowCount,
logsDeleted: logs.rowCount,
cutoffDate: cutoff,
timestamp: new Date().toISOString()
}
};
};// Health Check Monitor (Every 5 Minutes)
Ping external services and log response times. Schedule with */5 * * * *.
health-check.jstypescript
export const handler = async (event) => {
const endpoints = [
{ name: 'Main API', url: 'https://api.yourapp.com/health' },
{ name: 'Auth Service', url: 'https://auth.yourapp.com/ping' },
{ name: 'Payment API', url: 'https://pay.yourapp.com/status' },
];
const results = await Promise.all(
endpoints.map(async (ep) => {
const start = Date.now();
try {
const res = await fetch(ep.url, { signal: AbortSignal.timeout(5000) });
return {
name: ep.name,
status: res.status,
ok: res.ok,
latency_ms: Date.now() - start
};
} catch (err) {
return {
name: ep.name,
status: 0,
ok: false,
latency_ms: Date.now() - start,
error: err.message
};
}
})
);
const allHealthy = results.every(r => r.ok);
// If any service is down, you could fire a webhook or send an alert
if (!allHealthy) {
const failed = results.filter(r => !r.ok);
console.error('UNHEALTHY SERVICES:', JSON.stringify(failed));
}
return {
statusCode: allHealthy ? 200 : 503,
body: {
healthy: allHealthy,
checked_at: new Date().toISOString(),
services: results
}
};
};// Data Sync Pipeline (Hourly)
Pull from an external API and push into your database. Schedule with 0 * * * *.
data-sync.jstypescript
// Requires layer: db-pool
const db = require('db-pool');
export const handler = async (event) => {
// Fetch latest data from external API
const res = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=10');
if (!res.ok) {
return { statusCode: 502, body: { error: 'Failed to fetch source data' } };
}
const posts = await res.json();
let created = 0;
let updated = 0;
let errors = 0;
for (const post of posts) {
try {
const existing = await db.getOne(
'SELECT id FROM synced_posts WHERE external_id = $1', [post.id]
);
if (existing) {
await db.query(
'UPDATE synced_posts SET title = $1, body = $2, synced_at = NOW() WHERE external_id = $3',
[post.title, post.body, post.id]
);
updated++;
} else {
await db.insert('synced_posts', {
external_id: post.id,
title: post.title,
body: post.body,
user_id: post.userId,
synced_at: new Date().toISOString()
});
created++;
}
} catch (err) {
errors++;
console.error('Sync error for post ' + post.id + ':', err.message);
}
}
return {
statusCode: 200,
body: { created, updated, errors, total: posts.length, synced_at: new Date().toISOString() }
};
};// Daily Report Email (Weekdays 9 AM)
Attach db-pool + email-sender layers. Schedule with 0 9 * * 1-5.
daily-report.jstypescript
// Requires layers: db-pool, email-sender
const db = require('db-pool');
const mailer = require('email-sender');
export const handler = async (event) => {
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
const date = yesterday.toISOString().split('T')[0];
// Aggregate yesterday's stats
const stats = await db.getOne(
'SELECT COUNT(*) as orders, COALESCE(SUM(total), 0) as revenue FROM orders WHERE created_at::date = $1',
[date]
);
const newUsers = await db.getOne(
'SELECT COUNT(*) as count FROM users WHERE created_at::date = $1', [date]
);
const html = '<h2>Daily Report — ' + date + '</h2>'
+ '<table style="border-collapse:collapse">'
+ '<tr><td style="padding:8px;border:1px solid #ddd"><b>Orders</b></td><td style="padding:8px;border:1px solid #ddd">' + stats.orders + '</td></tr>'
+ '<tr><td style="padding:8px;border:1px solid #ddd"><b>Revenue</b></td><td style="padding:8px;border:1px solid #ddd">$' + Number(stats.revenue).toFixed(2) + '</td></tr>'
+ '<tr><td style="padding:8px;border:1px solid #ddd"><b>New Users</b></td><td style="padding:8px;border:1px solid #ddd">' + newUsers.count + '</td></tr>'
+ '</table>';
await mailer.send({
to: 'team@yourcompany.com',
subject: 'Daily Report — ' + date,
html
});
return {
statusCode: 200,
body: { sent: true, date, orders: stats.orders, revenue: stats.revenue }
};
};// Cron Expression Reference
┌──── minute (0-59)
│ ┌──── hour (0-23)
│ │ ┌──── day of month (1-31)
│ │ │ ┌──── month (1-12)
│ │ │ │ ┌──── day of week (0-7)
│ │ │ │ │
* * * * *
│ ┌──── hour (0-23)
│ │ ┌──── day of month (1-31)
│ │ │ ┌──── month (1-12)
│ │ │ │ ┌──── day of week (0-7)
│ │ │ │ │
* * * * *
* * * * *Every minuteHealth check pings*/5 * * * *Every 5 minutesStatus monitoring0 * * * *Every hourData sync pipelines0 0 * * *Daily at midnightDatabase cleanup0 9 * * 1-5Weekdays at 9 AMDaily reports0 0 * * 0Sunday midnightWeekly aggregation0 0 1 * *First of monthMonthly billing// API Reference
GET/api/cronList all cron jobs
POST/api/cronCreate cron job
PATCH/api/cron/:idUpdate cron job
POST/api/webhooks/cron/runManually trigger a cron job