logo

How to Schedule Recurring Tasks with Cron Expressions

Need to run a task every hour, daily at midnight, or every Monday at 9 AM? AsyncQueue handles recurring background job scheduling without cron servers, systemd timers, or AWS CloudWatch Events.

Why Not Traditional Cron?

Traditional cron jobs run on a single server:

  • If the server goes down, scheduled tasks stop silently
  • No retry logic — if a job fails, the result is lost
  • No logs or dashboard to inspect execution history
  • No way to scale across multiple machines

AsyncQueue solves all four problems.

Step 1: Choose a cron schedule

Cron expressions follow the standard 5-field format:

┌───────── minute (0-59)
│ ┌───────── hour (0-23)
│ │ ┌───────── day of month (1-31)
│ │ │ ┌───────── month (1-12)
│ │ │ │ ┌───────── day of week (0-7, 0 and 7 = Sunday)
│ │ │ │ │
* * * * *

Common examples:

ExpressionSchedule
*/5 * * * *Every 5 minutes
0 * * * *Every hour
0 9 * * *Daily at 9:00 AM
0 0 * * 1Every Monday at midnight
0 0 1 * *First of every month

Step 2: Create a scheduled task via the API

import { AsyncQueue } from 'asyncqueue-js';

const aq = new AsyncQueue({ apiKey: process.env.ASYNCQUEUE_API_KEY });

const task = await aq.tasks.create({
  callbackUrl: 'https://your-app.com/api/daily-report',
  schedule: '0 9 * * *',  // Every day at 9 AM
  payload: { reportType: 'daily-summary' },
  retries: 3,
});

console.log(`Scheduled task: ${task.id}`);

Step 3: Build your task handler endpoint

Create the endpoint that AsyncQueue invokes on each scheduled run:

app.post('/api/daily-report', async (req, res) => {
  const { reportType } = req.body;

  const report = await generateReport(reportType);
  await sendReportEmail(report);

  res.status(200).json({ success: true, reportId: report.id });
});

Step 4: Add retry configuration

If a scheduled execution fails (e.g., your database is briefly offline), retries with exponential backoff ensure the job still completes:

const task = await aq.tasks.create({
  callbackUrl: 'https://your-app.com/api/daily-report',
  schedule: '0 9 * * *',
  payload: { reportType: 'daily-summary' },
  retries: 3,
  backoff: 'exponential',
  backoffDelay: 5000,  // 5 second initial delay
});

Retries complete before the next scheduled window, so runs never overlap.

Step 5: Monitor scheduled executions

The AsyncQueue dashboard shows:

  • Next scheduled run for each recurring task
  • Execution history with status, duration, and response data
  • Failure alerts when a scheduled task fails all retry attempts
  • Pause/resume controls to temporarily stop a schedule

Managing Scheduled Tasks

// List all scheduled tasks
const tasks = await aq.tasks.list({ type: 'scheduled' });

// Pause a schedule
await aq.tasks.pause('task_abc123');

// Resume a schedule
await aq.tasks.resume('task_abc123');

// Delete a scheduled task
await aq.tasks.delete('task_abc123');