Service · One-shot

Run an on-demand script.

An on-demand script is an ephemeral container: it starts, runs once, captures every line of stdout and stderr, exits, and tears itself down. Trigger it manually from the dashboard, programmatically through the API, or on a cron schedule. The right service type for migrations, backups, scheduled email sends, billing reconciliations, and any one-shot task you'd otherwise hack together with a CI workflow.

How it works

Configure once, trigger any time

Run once, capture output, exit

1. Pick "Script"

From the dashboard, click New service → Script. Pick the repo and branch. Same auto-detected build phase as APIs and workers — Node, Python, Go, Ruby, Rust, Java, PHP. We build a container image once and reuse it for every run.

2. Set the run command

Examples: npx prisma migrate deploy, python manage.py migrate, bundle exec rake db:migrate, node scripts/send-weekly-digest.js, ./bin/backup.sh. Set a max duration (default 15 min, max 1h) — if the script runs longer, we kill it and mark the run as timed_out.

3. Choose how it gets triggered

Three trigger types: Manual (click "Run" in the dashboard), API (POST /v1/scripts/{id}/runs with a workspace token), or Cron (a standard 5-field cron expression — e.g., 0 4 * * * for daily 04:00 UTC). A script can have all three at once.

4. Each run is recorded

Every run keeps the full stdout/stderr, the exit code, the duration, and who or what triggered it (user, API token, cron). The dashboard shows recent runs at a glance with green/red status badges.

What you get

A first-class place for one-shot work

Cron without the cron server

You don't run cron yourself. We do. Schedule expressions are evaluated in UTC, the trigger creates a fresh container run, and the run history is queryable from the dashboard or API. Catch-up policy is configurable per-script: skip missed runs (default) or run the most recent one when the server comes back.

API trigger with payloads

POST /v1/scripts/{id}/runs with a JSON body to start a run. The body is exposed to the script as a HOSTINGGURU_RUN_INPUT env var. Useful for "send email to user X" or "regenerate report Y" — anything where the script is the worker but the trigger is event-driven.

Concurrency control

Default is one run at a time per script — if a run is in progress when the trigger fires, the new run is either queued or skipped (configurable). Avoids the "two backup processes fighting over a lock" footgun.

Exit-code-aware

Exit code 0 = success. Anything else = failure, surfaced in the dashboard with a red badge and the last 50 lines of stderr inline. Failure notifications go to email or Slack (Pro+ — wire up a webhook in workspace settings).

Same image as your other services

If the script lives in the same repo as your API, we cache layers across the two service types — installing dependencies once, reusing them. The script container has access to the same env vars and the same connection strings (Postgres, Redis) as your API.

Auto-cleanup

The container is removed after the run. No leftover state, no zombie processes, no manual docker prune. Disk space stays predictable on your dedicated server.

Common patterns

When a script is the right tool

FAQ

Common questions

How is this different from a worker?

A worker is a process that stays running. A script is a process that runs once and exits. If your task takes seconds-to-minutes and runs occasionally, use a script. If it runs continuously and waits for work, use a worker.

How is this different from a CI cron job?

You don't pay CI minutes for it. The script runs on your dedicated infrastructure, has access to the same env vars and connection strings as your other services, and lives next to your code. CI is fine for repo-level tasks like running tests; on-demand scripts are for application-level tasks like sending tonight's emails.

What's the maximum duration?

1 hour. If you need longer, restructure the work — paginate it, checkpoint state to Postgres, and resume on the next run. Long-running tasks are usually a worker, not a script.

How do I authenticate the API trigger?

Generate a workspace API token in Settings → API tokens. Send it as Authorization: Bearer <token> with the workspace ID in the X-Workspace-Id header. Tokens can be scoped to "trigger scripts only" so they can't read other workspace state.

Can a script trigger another script?

Yes — call the same API endpoint from inside a script using your workspace API token. Useful for fan-out: a "daily roll-up" script that triggers per-tenant report scripts in parallel.

What if I miss a cron window because the server was down?

Default is to skip missed runs and resume on the next scheduled tick. Switch to catch-up mode if you want the most recent missed run executed when the server returns. We don't run all missed runs — that's almost always wrong.

Stop hacking together cron in CI.

Scheduled scripts that live next to your code, with full run history.

Summary

Key takeaways

An on-demand script is an ephemeral container that runs a single command against your app's environment and exits. It is HostingGuru's equivalent of a Heroku one-off dyno or a Render Job.

  • Use scripts for tasks that run once and finish: migrations, backfills, CSV exports, manual reconciliations.
  • Each script has access to the same code, env vars, and database credentials as your web service.
  • Trigger from the dashboard, the API, or a cron schedule (Pro plan and above).
  • Logs and exit code are surfaced in the dashboard for every run.

What kind of jobs run well as on-demand scripts?

Database migrations, monthly invoicing reconciliations, sending a one-off email batch, exporting a CSV report, importing a large fixture file, manually rotating a secret. Anything that finishes in under 60 minutes is a good fit.

How do I trigger an on-demand script from CI?

Use the HostingGuru REST API with a workspace-scoped bearer token. The endpoint POST /api/v1/scripts/<script-id>/run queues the run and returns a run ID you can poll for status and logs.

Related docs