getNodi

Running the Laravel scheduler where there is no cron

Laravel’s scheduler is excellent and it is not a scheduler. It is a dispatcher that needs something to call schedule:run every minute — and on a lot of modern hosting, there is nothing to do the calling.

What Laravel gives you

Laravel Task Scheduling. Schedules defined in routes/console.php, dispatched by a single crontab entry that runs schedule:run every minute.

What Laravel provides
The schedule definition and dispatcher
What you provide
A cron entry, every minute, forever
Granularity
Down to every second, via sub-minute tasks
Timezone
Per-task, or schedule_timezone in config

Checked against Laravel docs on 18 August 2026. These change — if a deploy disagrees with this page, believe the deploy and tell us.

When this is the right answer

Most people reading this should keep what they have. It is worth being specific about when:

  • You have a server, or Forge, or anything with a real crontab. Add the line and stop thinking about it — this is the intended setup and it works well.
  • You are on Laravel Cloud or a platform that manages scheduled execution for you.

Where it runs out

Serverless and many shared hosts have no crontab

Vapor, containers with no cron daemon, and shared hosting with the cron panel disabled all leave you with a scheduler nothing is driving. The tasks are defined and simply never fire.

Nothing tells you the minute-ticker died

If the crontab entry stops — a rebuilt server, a changed path, a full disk — every scheduled task in the application silently stops with it. There is no error, because nothing ran to produce one.

Laravel’s own docs warn about timezone scheduling

They recommend avoiding per-task timezones where possible, because a daylight saving change can make a task run twice or not at all.

Scheduling it from outside

Expose schedule:run behind a guarded route and call it every minute from outside. The schedule definitions do not change at all — only what pulls the trigger.

routes/web.php

Route::post('/internal/schedule-run', function (Request $request) {
    abort_unless(
        hash_equals(config('app.cron_secret'), $request->header('X-Cron-Secret', '')),
        401
    );
    Artisan::call('schedule:run');
    return response()->json(['ok' => true]);
});

Point a job at it every minute with that header as a secret. You get the thing a crontab line never gave you: a record of every tick, and an alert the first time one does not happen. If sub-minute tasks are defined, note that schedule:run holds the whole minute — size your timeout accordingly.

What getNodi adds

getNodi calls a URL on a schedule and tells you what happened. Any schedule down to your plan’s floor, in your timezone rather than UTC, with retries, a record of every run — status, latency, response — and an alert the first time one fails. Credentials are encrypted at rest and requests can be HMAC-signed so your endpoint can verify they came from us.

The free plan runs 3 jobs hourly and needs no card, which is enough to find out whether this works for you. What it will not do is run a container, hold a connection open for an hour, or execute your code — it makes HTTP requests, and everything above is a way of making that enough.

Everything stated above about Laravel comes from its own documentation, linked at the top. We have tried to describe it as its makers would. ← What getNodi is