Scheduler
This guide explains how to configure and use Platformatic's built-in scheduler. The scheduler allows you to run periodic tasks by making HTTP requests at scheduled intervals using cron expressions. Note that the scheduler is in-memory only, so no information is persisted between restarts.
Overview
The Platformatic scheduler enables you to configure automated HTTP requests that run according to a specified schedule. This feature is useful for:
- Periodic data synchronization
- Scheduled maintenance tasks
- Recurring API calls
- Implementing workflows that need to run at specific times
Configuration
The scheduler is configured using an array of job definitions in your Platformatic configuration file.
Here's a basic example:
//...
"scheduler": [
{
"name": "my-scheduled-job",
"cron": "*/5 * * * *",
"callbackUrl": "http://localhost:3042/my-endpoint",
"method": "GET"
}
]
//...
Job Configuration Options
Each job in the scheduler can include the following options:
| Option | Type | Required | Description |
|---|---|---|---|
name | String | Yes | A unique identifier for the job |
cron | String | Yes | A cron expression defining the schedule |
callbackUrl | String | Yes | The URL to call when the job is triggered |
enabled | Boolean | No (defaults to true) | If false, the job is disabled. |
method | String | No (defaults to 'GET') | HTTP method to use (GET, POST, PUT, DELETE) |
headers | Object | No | HTTP headers to include in the request |
body | String / Object | No | Request body (for POST/PUT requests) |
maxRetries | Number | No (defaults to 3) | Number of retries attempts |
Cron Expression Format
The scheduler uses standard cron expressions with an optional seconds field. Examples:
*/1 * * * * *- Every second0 */5 * * * *- Every 5 minutes0 0 * * * *- Every hour0 0 12 * * *- Every day at noon0 0 0 * * 1- Every Monday at midnight
See crontab.guru for more examples.
Example: call application in the mesh network
It is possible (and useful) to call also applications in the platformatic mesh network.
Here's an example configuring a job that sends a POST request every minute to an
internal notification application (so exposed as http://notification.plt.local in the mesh network).
//...
"scheduler": [
{
"name": "send-message",
"cron": "0 */1 * * * *",
"callbackUrl": "http://notification.plt.local/message",
"method": "POST",
"headers": {
"content-type": "application/json",
},
"body": {
"message": "Scheduled notification",
"type": "info"
}
}
]
//..
External coordination
Watt exposes its scheduler through the runtime management API. A coordinator can inspect jobs, pause Watt's local trigger, and execute a job on demand:
| Operation | Management API |
|---|---|
| List jobs | GET /api/v1/scheduler |
| Pause a job | POST /api/v1/scheduler/:name/pause |
| Resume a job | POST /api/v1/scheduler/:name/resume |
| Run a job | POST /api/v1/scheduler/:name/run |
The same operations are available from the Watt CLI:
wattpm scheduler [runtime]
wattpm scheduler:pause [runtime] <name>
wattpm scheduler:resume [runtime] <name>
wattpm scheduler:run [runtime] <name>
See the Watt CLI command reference for the command arguments and output details.
scheduler lists the jobs and their current pause and next-run state. The other commands pause, resume, or execute a
job immediately. The runtime argument can be a process ID or runtime name and can be omitted when only one runtime is
available.
The runtime API exposes the same list as getSchedulerJobs(), returning SchedulerJob[]. The HTTP management API and
control client wrap that list as { jobs: RuntimeSchedulerJob[] }.
Pausing a job stops future local triggers but does not cancel an execution that is already running. The coordinator should pause a job before taking ownership and resume it when returning ownership to Watt.
Scheduler execution is at least once. HTTP retries, coordinator retries, or ownership changes around a cron tick can run a job more than once, so scheduled handlers should be idempotent.
Nuxt scheduled tasks
Nuxt applications can hand their Nitro schedules to Watt by adding the Platformatic scheduler module:
export default defineNuxtConfig({
modules: ['@platformatic/nuxt/scheduler']
})
The module disables Nitro's in-process cron runner and reports the configured task groups to Watt. Watt registers them as application scheduler jobs and invokes the tasks through its internal communication channel. It does not add HTTP control routes to the Nuxt application.
Without an external coordinator, Watt executes these jobs locally. An external coordinator uses the same Watt pause, resume, and run operations as it does for jobs from the runtime configuration.
Nitro scheduled tasks
Nitro applications can use the same integration by adding the Platformatic scheduler module to nitro.config:
import { defineNitroConfig } from 'nitropack/config'
export default defineNitroConfig({
experimental: { tasks: true },
modules: ['@platformatic/nitro/scheduler'],
scheduledTasks: {
'0 0 1 1 *': ['smoke']
}
})
Define tasks in Nitro's tasks directory. The module disables Nitro's in-process cron runner, reports the configured
task groups to Watt, and writes a scheduler manifest to the production output. Watt registers the groups as application
scheduler jobs and invokes the tasks through its internal communication channel.
Nitro must have experimental.tasks enabled because Nitro scans task files before installing modules. The module also
enables this option for Nitro versions that scan modules later in the build lifecycle.
Without an external coordinator, Watt executes Nitro jobs locally. Coordinators can use Watt's pause, resume, and run operations described above. Scheduled execution is at least once, so Nitro task handlers should be idempotent.
Node scheduled tasks
Node applications export scheduledTasks and matching task handlers from their entrypoint's top level. Each cron
expression can run one or more named tasks:
export const scheduledTasks = {
'0 */5 * * * *': ['cleanup', 'syncUsers']
}
export const tasks = {
async cleanup ({ scheduledTime, app }) {
// ...
},
async syncUsers ({ scheduledTime }) {
// ...
}
}
Watt registers each schedule with its Runtime scheduler and invokes handlers with the scheduled timestamp. Task groups run concurrently; a failed handler marks the group as failed and lets the Runtime apply its normal retry policy.
See the Node.js scheduled tasks reference for the complete handler contract.