{"slug":"rapids-runs","title":"Rapids Runs","description":"A run executes your Rapids container's image once, on demand — the same image and environment your container serves traffic from, but started as a single job instead of a scaled service. This is the r...","section":"Features","url":"https://docs.danubedata.ro/rapids-runs","markdown_url":"https://docs.danubedata.ro/rapids-runs.md","breadcrumbs":[{"title":"Features","slug":null},{"title":"Rapids","slug":"serverless-overview"},{"title":"Rapids Runs","slug":"rapids-runs"}],"headings":[{"level":1,"title":"Rapids Runs","id":"rapids-runs"},{"level":2,"title":"Why not just scale the container?","id":"why-not-just-scale-the-container"},{"level":2,"title":"Starting a run","id":"starting-a-run"},{"level":3,"title":"Only one run at a time per container","id":"only-one-run-at-a-time-per-container"},{"level":2,"title":"Run status","id":"run-status"},{"level":2,"title":"Listing runs","id":"listing-runs"},{"level":2,"title":"Reading logs","id":"reading-logs"},{"level":2,"title":"Cancelling a run","id":"cancelling-a-run"},{"level":2,"title":"Limits","id":"limits"},{"level":2,"title":"API abilities","id":"api-abilities"},{"level":2,"title":"Next steps","id":"next-steps"}],"format":"markdown","word_count":918,"content":"# Rapids Runs\n\n> **Preview:** Rapids runs are an early-access feature, available to select accounts while the API is reviewed. The shape described here may still change before general availability.\n\nA run executes your Rapids container's image **once**, on demand — the same image and environment your container serves traffic from, but started as a single job instead of a scaled service. This is the right tool for one-off work that shouldn't run as part of normal request traffic: database migrations, one-time backfills, cache warm-ups, or a maintenance script bundled into your image.\n\nRuns are separate from your container's normal scaling. Starting a run does not scale your container up or down, and a run in progress does not affect the replicas serving live traffic.\n\n## Why not just scale the container?\n\nScaling a container's replicas to run a one-off script — for example to apply a database migration before a deploy — runs into a mismatch: scaling creates a Knative **revision**, and a revision's startup work can run more than once (Knative may start additional replicas of the same revision under load, or retry a replica that failed to become ready). A migration that isn't safe to run twice concurrently should not be triggered this way.\n\nA run avoids this: it executes your image exactly once, as a single Kubernetes Job, with no autoscaling and no retries.\n\n## Starting a run\n\n```bash\ncurl -X POST https://api.danubedata.ro/api/v1/serverless/{container_id}/runs \\\n  -H \"Authorization: Bearer YOUR_API_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"command\": [\"php\", \"artisan\", \"migrate\", \"--force\"],\n    \"timeout_seconds\": 900\n  }'\n```\n\nAll fields are optional:\n\n| Field | Type | Description |\n|-------|------|--------------|\n| `command` | `string[]` | Overrides the image's entrypoint for this run. 1–32 items, each up to 4096 characters. Omit it to run the image's own default startup command. |\n| `image_tag` | `string` | Run a different tag of your container's **own image repository** for this run only — e.g. to run a migration from a specific build. The repository itself can never be changed by a run. |\n| `env` | `object` | Extra environment variables for this run only, layered on top of (and overriding) your container's normal environment. Up to 50 keys, each `UPPER_SNAKE_CASE`-style (`[A-Za-z_][A-Za-z0-9_]*`). **Values are never stored or returned** — only the key names appear in the run object, so you can see what was overridden without the values being retrievable afterward. |\n| `timeout_seconds` | `integer` | How long the run may execute before it is stopped and marked timed out. 60–3600 (1 hour max). Defaults to 900 (15 minutes). |\n\nA successful request returns `202` with the new run:\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": \"0192f3b0-...\",\n    \"container_id\": \"0192f1a0-...\",\n    \"status\": \"queued\",\n    \"terminal\": false,\n    \"command\": [\"php\", \"artisan\", \"migrate\", \"--force\"],\n    \"image\": \"cr.danubedata.ro/acme/api:latest\",\n    \"env_keys\": [],\n    \"timeout_seconds\": 900,\n    \"exit_code\": null,\n    \"message\": null,\n    \"created_at\": \"2026-09-16T18:00:00+00:00\",\n    \"started_at\": null,\n    \"finished_at\": null,\n    \"duration_seconds\": null\n  },\n  \"error\": null,\n  \"meta\": {}\n}\n```\n\n### Only one run at a time per container\n\nA container can have at most one run **queued** or **running** at once. Starting a second run while one is already active returns `409`:\n\n```json\n{\n  \"success\": false,\n  \"data\": null,\n  \"error\": {\n    \"code\": \"serverless.run_in_progress\",\n    \"message\": \"A run is already in progress for this container.\",\n    \"retryable\": true\n  },\n  \"meta\": { \"active_run_id\": \"0192f3b0-...\" }\n}\n```\n\nWait for the active run to finish (or [cancel it](#cancelling-a-run)) before starting another.\n\n## Run status\n\n| Status | Terminal | Meaning |\n|--------|----------|---------|\n| `queued` | No | Accepted; the Kubernetes Job is being created. |\n| `running` | No | The image is executing. |\n| `succeeded` | Yes | The image exited with status `0`. |\n| `failed` | Yes | The image exited with a non-zero status, or the run could not be started. See `message`. |\n| `cancelled` | Yes | Stopped by a `cancel` request. |\n| `timed_out` | Yes | Still running when `timeout_seconds` elapsed. |\n\nPoll `GET /api/v1/serverless/{container_id}/runs/{run_id}` until `terminal` is `true`.\n\n## Listing runs\n\n```bash\ncurl https://api.danubedata.ro/api/v1/serverless/{container_id}/runs \\\n  -H \"Authorization: Bearer YOUR_API_TOKEN\"\n```\n\nReturns runs newest first, 20 per page, with pagination in `meta`:\n\n```json\n{\n  \"success\": true,\n  \"data\": [ { \"id\": \"...\", \"status\": \"succeeded\", \"...\": \"...\" } ],\n  \"error\": null,\n  \"meta\": { \"current_page\": 1, \"per_page\": 20, \"total\": 3 }\n}\n```\n\n## Reading logs\n\n```bash\ncurl https://api.danubedata.ro/api/v1/serverless/{container_id}/runs/{run_id}/logs \\\n  -H \"Authorization: Bearer YOUR_API_TOKEN\"\n```\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"run_id\": \"0192f3b0-...\",\n    \"source\": \"live\",\n    \"logs\": \"Migrating: 2026_09_16_190000_create_...\"\n  },\n  \"error\": null,\n  \"meta\": {}\n}\n```\n\n`source` is `live` while the run is still active (read directly from its pod), `stored` once the run has finished (a tail is captured at completion), or `none` if no logs are available yet.\n\n## Cancelling a run\n\n```bash\ncurl -X POST https://api.danubedata.ro/api/v1/serverless/{container_id}/runs/{run_id}/cancel \\\n  -H \"Authorization: Bearer YOUR_API_TOKEN\"\n```\n\nCancelling a `queued` or `running` run stops it immediately and marks it `cancelled`. Cancelling a run that has already finished returns `409` with `error.code: \"serverless.run_not_active\"`.\n\n## Limits\n\n- **Timeout:** 60–3600 seconds (1 hour), 900 by default.\n- **Command:** up to 32 arguments, each up to 4096 characters.\n- **Environment overrides:** up to 50 keys per run; values are not persisted or returned.\n- **Concurrency:** one queued or running run per container.\n- **Resources:** a run uses the same CPU and memory profile as your container's own replicas.\n\n## API abilities\n\n| Endpoint | Ability |\n|----------|---------|\n| `GET /runs`, `GET /runs/{id}` | `serverless:read` |\n| `POST /runs`, `POST /runs/{id}/cancel` | `serverless:write` |\n| `GET /runs/{id}/logs` | `serverless:diagnostics` |\n\n## Next steps\n\n- [Invoking Containers](https://docs.danubedata.ro/serverless-invoking) — how your container serves normal traffic\n- [Automation & Diagnostics](https://docs.danubedata.ro/rapids-automation) — inspecting a container's live state\n\n---\n\n**Questions?** Contact support at support@danubedata.ro\n","prev":{"title":"Automation & Diagnostics","slug":"rapids-automation","url":"https://docs.danubedata.ro/rapids-automation","markdown_url":"https://docs.danubedata.ro/rapids-automation.md","json_url":"https://docs.danubedata.ro/rapids-automation.json"},"next":{"title":"Container Registry","slug":"container-registry","url":"https://docs.danubedata.ro/container-registry","markdown_url":"https://docs.danubedata.ro/container-registry.md","json_url":"https://docs.danubedata.ro/container-registry.json"},"index_url":"https://docs.danubedata.ro/index.json"}