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.
On-demand scripts run on dedicated infrastructure. Available on Pro ($35/mo) and Custom plans. Scripts share the dedicated infrastructure with your APIs and workers. See pricing.
Configure once, trigger any time
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.
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.
When a script is the right tool
Database migrations
Run prisma migrate deploy, knex migrate:latest, alembic upgrade head, or rails db:migrate as a script triggered manually before/after a deploy. Decouples migration time from deploy time and keeps migration logs in one place.
Daily / nightly jobs
Generate yesterday's reports, send a daily digest email, refresh denormalized tables, ping a Slack channel. Cron-triggered, runs in <15 min, exits.
Backups
pg_dump a managed Postgres database to S3 (or another object store). Cron-triggered nightly. The script holds the credentials; the backup target lives outside the workspace so a compromise of one service doesn't compromise both.
Webhook fanout / async tasks
Your API receives a webhook, kicks off a script run via the API trigger, returns 200 to the caller immediately. The script does the slow work — image resizing, PDF generation, AI inference — without blocking the request.
Monthly billing reconciliation
On the 1st of each month, walk every workspace's Stripe invoices and verify the line items match what the platform thinks should be billed. Cron expression: 0 6 1 * *.
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.
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.