Skip to content

Self-hosted: external cron mode — disable the in-process scheduler and expose the token cron route on the node preset #707

Description

@warmwind

Problem

With eve build && eve start (node preset), schedules are baked into nitro.options.scheduledTasks at build time and fired by the in-process cron runner, with no way to turn that off. For self-hosted deployments this means:

  • N replicas fire every schedule N times — there is no coordination between processes;
  • ticks that land while the process is down are silently lost, with no catch-up;
  • a hosting platform cannot pause a schedule or trigger one manually — production exposes no dispatch endpoint (/eve/v1/dev/schedules/:scheduleId is dev-only);
  • the container must stay always-on just to keep the clock, which blocks scale-to-zero.

None of this applies on Vercel, because the platform owns the clock: Vercel Cron POSTs to the unguessable /eve/v1/cron/<token> route emitted by createEveCronHandlerRoute. But applyEveCronHandlerRoute is a no-op for non-Vercel presets, so self-hosted deployments cannot get the same contract. Discussion #83 lists Vercel Cron among the conveniences you give up when self-hosting.

Proposal

Open the mechanism that already exists for Vercel to the node preset:

  1. A build-time switch (e.g. EVE_EXTERNAL_CRON=1): schedule task handlers are still registered, but nothing is written to scheduledTasks, so the in-process runner never starts.
  2. With the switch on, register the same token cron handler route on the node preset, reusing createEveCronHandlerRoute.
  3. Emit a manifest in the build output (token route path + cron list) that the hosting platform can read — the equivalent of config.crons[] on Vercel. The platform is the builder, so the secret path never leaves its hands.

The request contract stays identical to Vercel's: a header identifies the due cron expression, the unguessable path authenticates the caller, and CRON_SECRET can be layered on top. Optional extension: accept a schedule name for precise single-schedule dispatch, so platforms can offer a manual "run now".

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions