---
title: Deploying | Runware Docs
url: https://runware.ai/docs/serverless/deploying
description: How your source becomes a running version, what the platform does during a rollout, and what it will not ship.
relatedDocuments:
  - https://runware.ai/docs/serverless/versions
  - https://runware.ai/docs/serverless/invoking
  - https://runware.ai/docs/serverless/troubleshooting
  - https://runware.ai/docs/serverless/volumes
---
## Introduction

One command covers both creating an app and updating one. **The `--id` decides which.**

```bash
runware serverless deploy ./model.py --id my-app --gpu-type l40s --wait
```

A first deploy with a new id **creates the app**. A later deploy with the same id uploads a new source, records the next version, and rolls it once the build is ready.

## What gets uploaded

The **whole source directory** is zipped, not just the entry file, so your app can import its own modules and read its own data files. The working directory is the source root unless `--src-dir` says otherwise, and the entry file has to live inside it.

Keep files out of the upload with a `.runwareignore` at the source root, in gitignore syntax.

> [!WARNING]
> **Your `.gitignore` is not consulted.** What a project keeps out of version control is a different question from what it ships to a build, and the platform treats them separately.

Some things never travel regardless: **`.env` files**, `.git`, `__pycache__`, `.venv`, `node_modules` and the usual build and tool caches.

**The archive is capped at 10 MiB**, and the CLI checks before it uploads, so an oversized tree fails on your machine rather than after a transfer. That cap is for your code, not for your weights: fetch those in `load` from a [volume](https://runware.ai/docs/serverless/volumes) or the mounted cache, which is where they belong anyway.

## Create-time and later

This is the distinction worth learning first, because getting it wrong fails the deploy.

1. **Create only**

   `--gpu-type`, the worker settings, `--volume`, `--env`, `--env-file` and `--name`. **Passing any of these to a deploy on an app that already exists fails**, because they belong to the app, and a deploy carries your source.

2. **Every deploy**

   The source itself. Each one uploads, builds and records the next version.

3. **Changed elsewhere**

   Workers with `apps scale`, secrets with `secrets attach`. **Volumes are fixed** once the app is created.

## Build, then roll

A deploy returns as soon as the intent is recorded. **The work happens afterwards**, which is why `--wait` exists.

A build moves through `queued`, `building`, and then `ready` or `failed`. A build that is overtaken by a newer one becomes `superseded` and is canceled.

> [!NOTE]
> `--wait` polls until the app is `active` or `failed`, so the command finishes when the deploy does rather than when the upload does. **A successful wait is still not a running worker**: with `minWorkers` at `0` the app sits scaled to zero until the first invocation.

## What a rollout actually does

The platform **starts workers on the target version, waits for at least one to become healthy, switches routing, and only then drains the old ones**.

Old workers get a fixed grace period to finish what they are holding before they are terminated.

> [!NOTE]
> **If the new workers never become healthy, the old ones stay up** and the app carries on serving the previous version. A broken deploy costs you the build. Your uptime holds.

## Rolling back

Rollback is the same operation as a deploy. **You deploy an older version number**, and it runs identically to going forward.

```bash
runware serverless apps versions activate my-app 7
```

No new version is created and **nothing is rebuilt**: the image that version already pinned is re-applied. Re-deploying the version that is currently active is allowed too, and re-applies it.

## A stopped app records rather than rolls

Deploying to a stopped or stopping app is permitted, and it **records the version without rolling anything**, because there are no workers to roll. The `202` does not mean a rollout happened.

That recorded version is what the app comes back on when it resumes.

## What it refuses

- A version number that does not exist, or that is not `ready`, returns `409`.
- A deploy to a `deleting` app returns `409`.
- A deploy to an app that does not exist, or was deleted, returns `404`.
- A source update on a `stopped` app returns `409`.
- A create, source update, deploy or resume whose capacity your organization's credit balance cannot back returns `402` with the shortfall, and nothing is rolled. That includes a deploy or a configuration change over a `failed` app. A deploy to a stopped app starts nothing and is not checked, and the resume is. See [Errors](https://runware.ai/docs/serverless/errors#insufficient-credit).
- The balance is checked again when the rollout starts. A rollout refused then fails, and the app's `error` event names `insufficient credit` or `credit suspended`.

## Deploying a container instead

`--container` points at a directory whose root holds a `Dockerfile` and a `container.yaml`, plus whatever the Dockerfile copies.

```bash
runware serverless deploy --id my-app --gpu-type h100 --container ./wrapper
```

**It cannot be combined with an entry file, `--src-dir`, `--base-image` or `--requirement`**, because those describe a build the platform is doing for you and a container deploy is one you have already done.

An invalid `container.yaml` is **rejected at create**: `400` if it cannot be parsed, `422` if it parses and breaks a rule. See [Bringing a container](https://runware.ai/docs/serverless/bringing-a-container).