Skip to main content
A dev session runs your app against real Runpod hardware while you edit it. Start one with rp flash dev, pointing it at the file that defines your app:

What happens in a session

  1. The SDK imports your module and finds every runpod.App and its resources.
  2. It creates a temporary endpoint for each queue and API resource. Tasks provision a Pod each time they’re called.
  3. It runs the function marked with @runpod.local_entrypoint on your machine. Calls such as fn.remote() go to the temporary endpoints.
  4. Output that your remote functions print streams back to your terminal.
  5. The session watches your project for file changes. When you save, it re-scans the app and refreshes the endpoints, so the next run uses your new code.
  6. Press Enter to run the entrypoint again.
Press Ctrl-C to end the session. It waits for the running entrypoint to finish and then deletes the temporary endpoints. If cleanup fails, the command exits with an error and lists the endpoint IDs you need to delete yourself.
Dev sessions don’t run a local HTTP server. Your entrypoint calls remote functions directly, and you call @app.api routes through the class, for example Counter.post("/bump", {"by": 3}).

Run once for scripts and CI

To run the entrypoint a single time, clean up, and exit, add --once:
The command exits with an error if the entrypoint fails, so you can use it as a smoke test in CI.

Python version

In a dev session, and for every task call, the SDK sends your function to the worker as a serialized payload produced by your local Python. The worker must run the same Python version, so your local interpreter must be one of the supported versions: 3.10, 3.11, 3.12, 3.13, or 3.14. An unsupported version fails with an error before anything is provisioned.

Write code that works in a session

  • Keep blocking work out of module scope. The SDK imports your module to discover resources. Put long-running code inside the entrypoint or a remote function. If discovery hangs on an import, interrupt it with Ctrl-C.
  • Import heavy packages inside functions. Packages such as torch only need to exist on the worker.
  • Read volume paths inside remote functions. Volumes aren’t mounted on your machine. See Storage.
  • Guard local-only code with runpod.is_local(), which returns True everywhere except inside a Runpod worker.

Call styles

Inside an entrypoint, call your resources in whichever way suits the work: remote() and job.wait() don’t impose an execution timeout by default.

Spawned tasks

Calling .spawn() on a task returns a job that owns its Pod:
  • await job.wait(timeout=...) waits for the result, then tries to terminate the Pod, including when the wait times out or the task fails.
  • await job.cancel() abandons the task and terminates its Pod.
  • If you exit without waiting or cancelling, the task keeps running. Tasks can run indefinitely, so detached tasks keep billing until they finish.
  • If the SDK can’t delete a task’s Pod, it prints a warning and keeps the ID in job.pod_id. Check the Pods page and terminate it yourself.

Costs

Temporary endpoints and task Pods bill like any other Serverless worker or Pod while they run. Dev sessions delete endpoints when you exit, but they don’t delete volumes. See Storage.

Next steps

Last modified on October 15, 2026