Worker models
Every project picks a worker model, and the choice has real consequences. Get it wrong and a scheduled job can run once per core instead of once.
Standard recommended
One real worker process per licensed core, all serving in parallel. This is real multi-core — four licensed cores means four workers handling requests simultaneously.
It works for ordinary applications and for fork-and-serve cluster code alike. If your application calls
cluster.fork(), that call is skipped, because the engine has already forked real
workers for you.
WORKER_NUMBER and cluster.worker.id are the
real worker number under Standard. A guard like
if (cluster.worker.id === 1) runs your cron exactly once, on one worker —
which is the pattern you want.
Self-coordinating cluster single core
Your entire application — its master and the workers it forks — runs emulated inside one process on one core. There is no parallelism.
Choose it only when your master does coordination the engine cannot replace: aggregating messages from workers over IPC, distributing jobs, holding state the workers ask it for.
If your master only forks and respawns, use Standard instead. That is the common case, and Standard gives you the cores you are paying for.
Single instance single core
One copy, one core. For applications that must never run twice and cannot be adapted — in-memory sessions or caches with no shared store, or a scheduler with no worker guard.
It is the safe answer when you are unsure and cannot change the code. It is also the slowest, so treat it as a stopgap rather than a destination.
Choosing
| Your application | Model |
|---|---|
| An ordinary web app or API | Standard |
Uses cluster.fork() just to spread load | Standard — your fork is skipped, the engine already did it |
| Runs a cron guarded by a worker check | Standard — the guard works as written |
| Runs a cron with no guard | Single instance, or add a guard and use Standard |
| Keeps sessions or a cache in process memory | Single instance, or move state to Redis and use Standard |
| Master aggregates worker messages over IPC | Self-coordinating cluster |
The failure to avoid
setInterval or cron under Standard
runs in every worker. Four cores means four invoices emailed, four cleanup jobs, four webhook retries.
Nothing errors — it just happens four times, which is worse.
The fix is one line, and it is the same line you would want on any clustered Node deployment:
const cluster = require('cluster')
if (cluster.worker.id === 1) {
startScheduler()
}
Changing it later
The worker model is on the project’s General pane and can be changed at any time. It takes effect on the next push or reload.