@app.queue) and API (@app.api) resources. Tasks (@app.task) provision one Pod per call and don’t scale.
Production
- Pin GPUs to a specific pool or device instead of
GpuGroup.ANY, so performance and cost are predictable. - Keep workers warm for latency-sensitive work by setting a minimum of 1 or more.
- Set
execution_timeout_msso a stuck job can’t run indefinitely. - Store secrets with
runpod.Secret, not as plain values inenv. - Cache model weights with
modelor a network volume, so workers don’t download them on every cold start.
Queue resources
Jobs can wait in the queue, so a small warm pool is usually enough:API resources
HTTP clients expect an immediate response, so keep more workers ready and add a health route:@runpod.init method so it’s ready before the worker takes traffic.
Development
- Use
GpuGroup.ANYor a list of GPUs so workers start quickly. - Keep the maximum low, for example
workers=(0, 2), to limit spend while testing. - Use a short
idle_timeout, such as 300 seconds, so workers scale down between runs. - Iterate with
rp flash dev, which deletes its temporary endpoints when you exit. See Dev sessions.
Cost control
- Scale to zero with a minimum of 0 workers. The default,
(0, 3), already does this. - Use the smallest GPU that fits, or a CPU instance when you don’t need a GPU.
- Shorten
idle_timeoutfor infrequent traffic. - Batch work into fewer, larger jobs.
- Delete volumes you no longer need. Volumes keep billing after you undeploy an app.
Trade-offs
Checklist before deploying
- GPUs are pinned for production resources.
- Latency-sensitive resources have a minimum of at least 1 worker.
execution_timeout_msis set.- Secrets use
runpod.Secret, and every variable workers need is passed throughenv. - Large models are cached with
modelor a volume. - API resources have a health route.
- The app runs cleanly with
rp flash dev main.py --once.