Run your app on a timetable with scheduled jobs (cron) on BrewInTH

Morning summary emails, nightly clean-ups: the Schedules tab, why not an in-app timer, setting the start time, and AI-made jobs that stop with the token.
A site in real use usually has work that must happen again and again without anyone pressing a button: a sales summary email every morning, clearing temporary files every night, fetching new prices or exchange rates every hour, reminding customers before an appointment. Ask an AI to put a timer inside the app, and sometimes the job simply never runs, because the app was asleep or had just been redeployed.
This guide shows how to use BrewInTH's Scheduled jobs (cron) so your app does its work on a timetable: having the AI write the script, testing it, setting the frequency, and the details that stop a job from quietly going silent.
In short
✅ The Schedules tab of an app project runs a command every 5 minutes up to every week, up to 10 jobs
✅ Each run starts in its own container from the image of the live release, with all app settings, for up to 4 hours
✅ Jobs run even while the app sleeps on the Free plan, unlike a timer inside the app
✅ The timetable counts from when you create the job; want 3 a.m.? Press Run now at 3 a.m.
✅ Jobs an AI creates with a token stop when that token expires; create long-term jobs yourself in the console
What scheduled jobs are and what they are for
A scheduled job (or cron job) is a command the platform runs on a timetable, with no visitor needed. Common uses:
- emailing the shop owner yesterday's orders or bookings every morning;
- sending customers a reminder before their appointment;
- clearing temporary files or old sessions every night;
- pulling data from outside, such as prices, exchange rates or stock from another system, every hour;
- working through a queue, such as resizing photos users uploaded.
Scheduled jobs exist for app projects (Node, Python, PHP, Laravel, Go, Java, .NET, Ruby, Bun). A static site has no server-side program, so it has no such tab.
Why not put a timer inside the app?
Many AIs reach for an in-app scheduler such as node-cron or APScheduler. On real hosting that goes wrong:
- Apps on the Free plan sleep when nobody visits. While the app sleeps, its timer sleeps too, and the night-time job never happens.
- Every new release restarts the app, and the timer starts counting again.
- The app serves visitors and does heavy work at the same time, so the site slows down while the job runs.
BrewInTH's scheduled jobs run apart from the app that serves your visitors, so none of the three applies.

Set up a scheduled job, step by step
1. Have the AI write the job as a script that finishes
A scheduled job is a command that runs and ends, not a program that stays open. Tell the AI:
My shop wants an email summary of yesterday's bookings sent to owner@myshop.com every morning.
- Write it as a separate script, scripts/daily-summary.js, that ends by itself (exit 0 on success, exit 1 on failure).
- Use the same database and MAIL_* environment variables as the app.
- Print one short summary line (how many items were sent); never print passwords or full customer data.
- Running it twice on the same day must not send a second email (store the last sent date in the database).
- Do not use node-cron or any timer inside the app; I will set the timetable on BrewInTH myself.
Then publish again and test the script once with a sandbox command.
The "safe to run twice" rule matters: when you press Run now to test, or a run repeats, customers still get one email, not two.
2. Add the job on the Schedules tab
Open the project, go to the Schedules tab, and in Scheduled jobs (cron) fill in:
- Name, for example
daily-summary. - Command, for example
node scripts/daily-summary.js(Python:python scripts/daily_summary.py, PHP:php scripts/daily-summary.php). - Frequency: Every 5 minutes, Every 15 minutes, Every 30 minutes, Every hour, Every 6 hours, Every day or Every week.
- Timeout per run (seconds): 120 by default, up to 14,400 (4 hours). A run that takes longer is stopped.
Then press Add schedule.

3. Press Run now to test and to set the start time
The timetable counts from when you create the job. Create an "Every day" job at 14:20 and it first runs tomorrow at 14:20, then every day around that time.
The Run now button does two things:
- Tests right away: the Last run column shows whether it succeeded or the error message.
- Moves the daily time: the next run is counted from the moment you press it. For a daily job early in the morning, press Run now once at that time.
For a more exact time, run the job every 5 or 15 minutes and let the script check the local time itself, and whether it has already done today's work.
4. Look after your jobs
Each job's row shows Next run and Last run with a status. Pause stops a job for a while without deleting it; Delete removes it. Overdue means the time has come but the job has not run, for example because the project has no successful release yet.
Know this before you rely on scheduled jobs

- Jobs an AI created through a token stop when that token expires or is revoked. The token from the automatic link button lasts 24 hours, so a job the AI set up stops the next day. Create long-term jobs yourself on the Schedules tab (let the AI write and test the script, then add the job yourself). If the AI already created one, delete it and create it again in the console.
- Jobs run from the live release. After changing the script, publish again so the next run uses the new code.
- Files you want to keep must be in /data. Each run starts in a fresh container, and anything written elsewhere is gone when it ends. Keep data in the database, or switch on Persistent storage (/data) on the App settings tab.
- A paused project runs no jobs. An app that is only asleep (autosleep) still runs them as usual.
- Same power as the plan's app: split heavy work into small batches.
Example commands by stack
- Node.js:
node scripts/cleanup.js - Python / Django:
python manage.py clearsessions - PHP:
php scripts/cleanup.php - Laravel:
php artisan queue:work --stop-when-emptyevery 5 minutes for queued jobs, orphp artisan schedule:runevery 5 minutes with tasks in your code no more frequent than every 5 minutes - Ruby:
bundle exec rake cleanup
Watch the video (in Thai)
▶ From creating a project to opening the site (1:30)
Watch on YouTube
Frequently asked questions
Can a job run every minute?
No. The shortest interval is every 5 minutes. If something has to happen instantly, do it in the app when the request comes in.
How many jobs can I set?
Up to 10 per project. Several small tasks on the same timetable can share one script.
Do scheduled jobs use my quota?
A run uses the same CPU and RAM as the plan's app. Data sent through the site still counts as bandwidth, and files the job writes to /data count toward your plan's storage.
How do I know a job failed?
Read the status and error in the Last run column. For important jobs, ask the AI to make the script email or message you when it fails.
Can a static site run scheduled jobs?
No. A static site has no server-side program. For scheduled work, build the site as an app, for example in Node or Python.
Summary
For work that must repeat, have the AI write a script that runs, ends, and is safe to run twice. Test it with a sandbox command, add it yourself on the Schedules tab, pick a frequency, and press Run now at the time you want it to keep. The job keeps going even when the app sleeps or you publish a new release.
Start your first project free →
