Scheduled Functions on Netlify, and the one-hour floor
Netlify Scheduled Functions are on every plan and free, which is genuinely good. They also floor out at one hour, run only in UTC, and cannot be invoked by URL. Those three facts decide whether they fit.
What Netlify gives you
Netlify Scheduled Functions. A schedule set in netlify.toml or exported from the function itself. Available on all plans and enabled by default.
- Minimum interval
- One hour
- Timezone
- UTC
- Maximum execution
- 30 seconds
- Deploys
- Published deploys only — not previews or branches
- Manual invocation
- No URL — dashboard or CLI only
Checked against Netlify 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:
- Hourly or slower is what you actually need, and the work finishes in under 30 seconds.
- You want zero extra infrastructure and the job is not critical enough to need an alert when it fails.
Where it runs out
Anything under an hour is out
Every five minutes, every fifteen minutes, twice an hour — none of it is available at any price. This is the limit people actually hit.
30 seconds is short for a scheduled job
Scheduled work tends to be the slow kind: imports, digests, syncs. Netlify points you at Background Functions for longer runs, which is a different function type with a different deploy shape.
You cannot trigger it by URL
No payload, no manual HTTP invoke. Re-running a failed job means the dashboard or the CLI, and orchestrating it from anything else is not possible.
Scheduling it from outside
Turn the scheduled function into an ordinary Netlify Function — same code, no schedule export — and call it on the interval you wanted.
Drop the schedule, keep the handler
// netlify/functions/sync.ts
export default async (req: Request) => {
if (req.headers.get('x-cron-secret') !== Netlify.env.get('CRON_SECRET')) {
return new Response('Unauthorized', { status: 401 });
}
await sync();
return Response.json({ ok: true });
};
// no `export const config = { schedule: ... }`Point a job at https://your-site.netlify.app/.netlify/functions/sync with that header set as a secret. You also get the thing the built-in version has no answer for: a notification when it stops working.
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.