Ploy
Ploy
Features

Cron Triggers

Schedule your workers to run on a recurring basis using cron expressions.

Cron Triggers

Ploy Cron Triggers let you schedule your workers to run automatically on a recurring basis. Define cron expressions in your ploy.yaml and implement a scheduled handler to process them.

Configuration

Add cron triggers in your ploy.yaml:

ploy.yaml
kind: worker
build: pnpm build
out: dist
cron:
  EVERY_MINUTE: "* * * * *"
  HOURLY_CLEANUP: "0 * * * *"
  DAILY_REPORT: "0 9 * * *"

Each key is a trigger name (uppercase with underscores) and the value is a standard cron expression with 5 fields:

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

Basic Example

src/index.ts
export default {
	async fetch(request, env) {
		return new Response("Hello from cron worker!");
	},

	async scheduled(event) {
		console.log(`Cron triggered: ${event.cron}`);
		console.log(
			`Scheduled time: ${new Date(event.scheduledTime).toISOString()}`,
		);

		// Your scheduled logic here
		await performCleanup();
	},
} satisfies Ploy;

ScheduledEvent

The scheduled handler receives a ScheduledEvent with the following properties:

interface ScheduledEvent {
	/** The cron expression that triggered this execution */
	cron: string;
	/** Timestamp when the event was scheduled (ms since epoch) */
	scheduledTime: number;
	/** Call to signal this invocation should not be retried */
	noRetry: () => void;
}

Cron Expression Syntax

Standard 5-field cron expressions are supported:

ExpressionDescription
* * * * *Every minute
*/5 * * * *Every 5 minutes
0 * * * *Every hour
0 0 * * *Every day at midnight
0 9 * * 1-5Weekdays at 9 AM
0 0 1 * *First day of every month
30 2 * * 0Sundays at 2:30 AM

Supported Syntax

  • Wildcards: * matches all values
  • Specific values: 5 matches exactly 5
  • Ranges: 1-5 matches 1 through 5
  • Steps: */15 matches every 15th value
  • Lists: 1,3,5 matches 1, 3, and 5
  • Combined: 1-10/2 matches 1, 3, 5, 7, 9

Multiple Triggers

You can define multiple cron triggers, each identified by a unique name:

ploy.yaml
cron:
  CLEANUP: "0 * * * *"
  DAILY_DIGEST: "0 9 * * *"
  WEEKLY_REPORT: "0 10 * * 1"

Use the event.cron property to distinguish which trigger fired:

async scheduled(event) {
  switch (event.cron) {
    case "0 * * * *":
      await runCleanup();
      break;
    case "0 9 * * *":
      await sendDailyDigest();
      break;
    case "0 10 * * 1":
      await generateWeeklyReport();
      break;
  }
}

Using with the Start SDK

If you're using @meetploy/start, register a scheduled handler with .scheduled():

src/index.ts
import { ploy } from "@meetploy/start";

const app = ploy<PloyEnv>()
	.get(
		"/",
		{
			response: z.object({ status: z.string() }),
		},
		() => ({ status: "ok" }),
	)
	.scheduled(async (event, env, ctx) => {
		console.log(`Cron: ${event.cron}`);
		// Your scheduled logic
	})
	.build();

export default app;

Combining with Other Bindings

Cron triggers work alongside other Ploy bindings. Use queues, databases, and caches from your scheduled handler:

ploy.yaml
kind: worker
build: pnpm build
out: dist
db:
  DB: default
queue:
  TASKS: tasks
cron:
  HOURLY_SYNC: "0 * * * *"
async scheduled(event, env) {
  // Query your database
  const staleRecords = await env.DB.prepare(
    "SELECT id FROM records WHERE updated_at < ?"
  ).bind(Date.now() - 86400000).all();

  // Queue work for processing
  for (const record of staleRecords.results) {
    await env.TASKS.send({ action: "refresh", recordId: record.id });
  }
}

The scheduled handler has access to the same env bindings as your fetch handler.

Local Development

When running the emulator with ploy dev, cron triggers are automatically scheduled based on your ploy.yaml configuration. The emulator checks cron expressions every 15 seconds and invokes your scheduled handler when a match occurs.

Cron execution history is visible in the dev dashboard.

Next Steps

  • Queues - Process background jobs
  • Workflows - Orchestrate multi-step processes
  • Workers - Learn about Ploy workers

How is this guide?

Last updated on