NetrunHome

When something breaks

How to run a script on a schedule without cron

· 5 min read

In short

You can run a script on a schedule without cron by making the schedule part of the application itself: the script runs continuously and decides when to act, either with a loop and a sleep when exact timing does not matter, or with a scheduling library such as schedule or APScheduler in Python and node-cron in Node.js when you need a specific time of day. Netrun has no separate scheduler setting in the dashboard, so a project like this counts as a background script: it never goes idle, the free plan gives it 3 days of work, and running longer needs the Pro plan. Two things are worth handling up front: store the time of the last successful run in the persistent /data folder, because a restart resets the countdown, and set the time zone explicitly in code.

Normally a schedule means cron on your own server: one line in the crontab and the system starts the script every hour. The habit breaks the moment you no longer have a server of your own. There is no terminal in a managed dashboard, no crontab to edit, and people start looking for a "Schedule" tab. Netrun does not have one either, and it is fairer to say that up front than to let you hunt for it.

The approach that actually works is different, and simpler than it sounds: the schedule becomes part of the application. The script is not started by an alarm from outside, it stays running and decides for itself when it is time to work. Below are three ways to do that, the two traps that make a schedule drift or fire twice, and one plan detail worth knowing in advance.

  1. Put the pause inside the script when minutes do not matter#

    The simplest schedule is an endless loop: the script does the work, sleeps for a while and repeats. That is enough when frequency matters more than the exact clock time: roughly once an hour, every ten minutes, once a day. Keep in mind that the pause is counted from the end of the previous run rather than from the top of the hour, so the firing time slowly drifts if the work itself takes a while.

  2. Use a scheduling library when you need a specific time#

    If the job has to fire every day at 9am or on Mondays, a bare sleep loop is not enough and you want a scheduling library. In Python, schedule covers simple rules and APScheduler fits when there are many of them or you prefer cron-style expressions; in Node.js, node-cron plays the same role. The script still has to keep running: the library is an alarm clock inside your application, not an outside service that will start it for you.

  3. Ping your site from outside if you already have one#

    If a site or an API of yours is already published, the schedule can live outside it: add a dedicated route such as /tasks/hourly that does the work, and let an external cron-style service open that URL on a schedule. The URL is public, so protect it with a secret key in a query parameter or a header, and read that key from an environment variable. Keep the work short and answer quickly: a long response risks timing out on the caller side. The upside is that a site on the free plan lives indefinitely, sleeping when idle and waking up when the caller opens the link.

  4. Set the time zone explicitly#

    The server time zone is almost certainly not yours, so "9am" easily turns into some other hour. Do not rely on the machine local time: set the zone explicitly, with ZoneInfo and the scheduler time zone argument in Python, or the matching option of the library in Node.js. When in doubt, log the current time at startup so you can see immediately which zone your script is counting in.

  5. Record the last run in the persistent /data folder#

    After a restart, whether you shipped new code or the project came back up after a crash, the countdown starts over and the scheduling library has no memory of what it already did. So write the time of the last successful run to a file in /data: that folder survives code updates and restarts, and you can inspect it on the "Data" tab. Read the marker at startup and decide for yourself whether the run for today is already done and can be skipped, or was missed and should happen right away. Projects that ship their own docker-compose have no /data folder, so keep the same marker in a named volume or in a database.

  6. Upload the code and watch the first run in the logs#

    Upload the folder as a ZIP archive or import a repository from GitHub, including a private one, and the platform detects the language, installs dependencies and starts the script. Then open the logs in your dashboard: the startup is there, and so is every run if you log a line for it. For the first check it helps to set a short interval temporarily, confirm the job really fires, and only then put the real schedule back.

The short version: there is no scheduler as a separate dashboard setting, and there is no point looking for one, because the schedule lives inside your script. That also decides the plan side of things: a script that runs all the time never goes idle and nothing can wake it, so on the free plan a project like this gets three days of work and is then switched off. The code, the settings and the secrets stay in place, and a warning arrives a day before. If the job has to fire for weeks and months, the Pro plan is what you need, and current prices and limits are shown in the dashboard. Try Netrun.

Common questions

How do I run a Python script every hour?

Wrap the useful work in an endless loop with a one hour sleep, which is enough when frequency matters more than the exact minute. If the run has to land on the top of the hour, use a scheduling library: schedule for simple rules, or APScheduler when there are many of them. Either way the script keeps running, and it is published as an ordinary background project with no schedule to configure in the dashboard.

What happens to the schedule when the project restarts?

The countdown starts over: both a sleep loop and a scheduling library measure time from process start and remember nothing about earlier runs. Because of that a job can fire twice in a row, or miss its moment entirely if the restart happened right on it. The fix is a marker: write the time of the last successful run to a file in the persistent /data folder and check it at startup.

Why did my job run at the wrong time?

Usually the time zone: the server clock does not have to match yours, and "9am" is counted in the machine zone rather than in your city. Set the zone explicitly, with ZoneInfo and the scheduler argument in Python or the library option in Node.js. The second most common cause is a sleep loop, which counts the interval from the end of the previous run, so the firing time drifts a little each cycle.

schedule or APScheduler: which one should I use?

For one or two simple rules like every hour or every day at 9:00, schedule is easier: it reads almost like a sentence and needs no setup. APScheduler is worth it when there are many rules, you want cron-style expressions, or jobs have to run in parallel. In Node.js, node-cron usually covers both cases.

Can I run a job once a week or once a month?

Yes, rare schedules are supported by the same libraries as hourly ones. But the rarer the job, the more the last-run marker matters: between two runs the project will very likely go through a code update or a restart, and without a marker a whole month can pass with nothing happening. Keep the last run date in the persistent /data folder and check at startup whether a missed run should happen now.

How do I know the job actually ran?

Log one line per run, with the time and the result. Logs are visible in the dashboard in real time, so both a successful run and an error show up immediately. If the script crashes outright, the project is restarted and you get a notification, so a silent failure is not something you have to watch for.

Is there a way to run something on a schedule?

There is no separate schedule setting in the dashboard. Scheduling is done inside the application itself: the script runs continuously and decides when to act — with a loop and a pause, or with a scheduling library. A project like that counts as a background script: it does not sleep, so on the free plan it runs for 3 days, and continuous operation needs the Pro plan.

Do bots and background scripts sleep?

No, only websites sleep: a website wakes up by itself when someone opens it. A bot or a background script has nothing to wake it — nobody comes to them by link, they work on their own. That is why on the free plan they run for 3 days, and after that a bot needs the Pro plan to keep running around the clock.

Is my data kept when I update the code?

Yes, as long as your data lives in persistent storage. For a regular project that is the /data folder: anything your app saves there stays in place when you update the code or restart, and you can browse and download the files on the "Data" tab. If you described the services yourself in docker-compose, persistent storage means the named volumes from your file, and such a project has no /data folder. Files written outside persistent storage are created from scratch on the next deploy. Your project link stays the same either way.

Get your own project online

Upload your code, answer a couple of questions and get a working link. There is a free plan

Try Netrun
All blog articles