Skip to main content

Python cron jobs without the server.

A crontab on a box nobody patches, running a script that logs to a file nobody reads.

The standard setup.

A crontab entry on a Linux server, calling a Python script at an interval. Simple to start, expensive to maintain.

crontab
# crontab -e
0 8 * * 1 cd /home/deploy && python3 report.py >> /var/log/report.log 2>&1
  • Works on any Linux server with Python installed.
  • No queue, broker, or platform to install.
  • Familiar to anyone who has administered a Unix system.

Where it breaks.

The server is the single point of failure, and everything around it drifts.

  • The server has to stay up. A reboot, a disk failure, or a missed patch kills every job on the host.
  • No retry. A failed run is a missed run. You find out when someone notices the data is stale.
  • Logs go to stdout or a file. Finding what went wrong means SSH, grep, and hope.
  • The crontab and the script drift apart. Someone edits one without updating the other.
  • Dependencies rot. The Python version, the pip packages, and the OS underneath all age at different rates.
  • No rollback. A broken change means restoring from backup or rewriting under pressure.

qbash Tasks.

A Task is an AI automation written in Python, hosted on a managed runtime. A developer writes the script; anyone runs it from a form. Integrations, model calls, version control, and logging are built in.

Model and provider agnostic.

  • Anthropic
  • OpenAI
  • Gemini
  • xAI
  • OpenRouter
  • Amazon
  • Perplexity
  • MoonshotAI
  • Meta
  • Qwen

A scheduled task on a managed runtime.

Write the script, set the schedule, and the platform handles the server, the runtime, and the logs.

  • Set a cron expression and the task runs on schedule, with no server or process manager to maintain.
  • Every run is logged with inputs, output, errors, and duration.
  • Every save is a revision with a line-level diff and one-click rollback.
  • Retry with checkpoints. A failure picks up where it left off.
  • The runtime, the interpreter, and the Python environment are managed by the platform.
report.py
rows = aisle.integrations.postgres.execute_query(
    "SELECT department, sum(amount) FROM expenses "
    "WHERE date >= current_date - interval '7 days' "
    "GROUP BY department"
)

report = aisle.ai.run_prompt(
    slug="weekly-expense-summary",
    variables={"rows": rows},
)

aisle.integrations.slack.create_message(
    "#finance", text=report["summary"],
)

aisle.integrations.gmail.send_email(
    to="[email protected]",
    subject="Weekly expense summary",
    body=report["body"],
)

Runs without a host.

The server and the crontab are handled by the platform, and every run is logged with what happened.

Version history and rollback

Every save writes a revision with a line-level diff. The cron expression and the script live in the same place, so a change to either shows up in the same history. Any revision restores in one click.

Output goes where the work happens

Send results to Slack, email, Jira, or a database in one line. 45+ integrations with credentials brokered server-side. The cron job output goes where the team already works, not to a log file.

alert.py
issues = aisle.integrations.postgres.execute_query(
    "SELECT * FROM checks WHERE status = 'failing'"
)

if issues:
    aisle.integrations.slack.create_message(
        "#alerts",
        text=f"Found {len(issues)} failing checks",
    )

    for issue in issues:
        aisle.integrations.jira.create_ticket(
            summary=issue["name"],
            description=issue["details"],
        )

Parallel processing

Fan out over hundreds of items with concurrency and rate limiting as arguments. Checkpoints skip the items that already finished, so a retry does not repeat work.

batch.py
results = aisle.parallel(
    check_endpoint, endpoints,
    concurrency=10, max_per_minute=60,
    checkpoint="health-check", retry=2,
)

failures = [r for r in results if not r["healthy"]]

Questions

Can I set any cron schedule?

Yes. Standard cron expressions. The task runs on the managed runtime at the interval you set.

What if a scheduled run fails?

The run is logged with the error. You can configure retry with checkpoints so a failed run resumes where it left off rather than starting over.

How is this different from GitHub Actions on a cron?

GitHub Actions runs a workflow in a container on a schedule. A task is comparable in that it is scheduled, but the runtime is purpose-built for long-running Python with integrations, model calls, and persistent state. Actions has a 6-hour timeout, no built-in retry from a checkpoint, and no run-level logging beyond workflow output.

Can a task run longer than a few minutes?

Up to 12 hours. Long-running data processing, backfills, and batch jobs are expected use cases.

What about APScheduler or the schedule library?

Those libraries run inside a long-lived Python process you host yourself. The server and the process manager are still yours to maintain. A qbash task removes both.

Competitor details reviewed . Vendors change plans and features without notice, so check theirs before deciding.

Ship your first task.

Put a script on a cron and it runs unattended, with every execution logged and every change versioned.