> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lazycloud.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Apps and workloads

> The kinds of workload you can run, and how an app deploys, prunes, and exports them as one unit.

A workspace holds apps, and an app holds workloads. A workload's decorator is
its whole definition: image, resources, volumes, secrets, schedule, and
scaling. Deploying makes the workspace match the code, with no dashboard
setting or CLI flag on top, so infrastructure changes arrive as one reviewable
diff.

## Workload kinds

| Kind                                                      | For                                         | Triggered by                                       | Scales                           |
| --------------------------------------------------------- | ------------------------------------------- | -------------------------------------------------- | -------------------------------- |
| [Function](/concepts/functions)                           | Batch jobs, background work, GPU tasks      | `.remote()`, `.map()`, `.spawn()`, `lazycloud run` | Autoscaler on queued calls       |
| [Schedule](/concepts/schedules)                           | Recurring work                              | A function's `cron`                                | Like a function                  |
| [Endpoint](/concepts/endpoints#endpoints)                 | An HTTP API from one function               | HTTPS requests                                     | Autoscaler on requests in flight |
| [ASGI app](/concepts/endpoints#asgi-applications)         | A FastAPI or Starlette app                  | HTTPS requests                                     | Autoscaler on requests in flight |
| [Realtime handler](/concepts/endpoints#realtime-handlers) | A WebSocket service                         | WebSocket messages                                 | Autoscaler on requests in flight |
| [Pod](/concepts/pods)                                     | A container command, such as a model server | Connections, or `create()`                         | By hand                          |
| [Sandbox](/concepts/sandboxes)                            | Generated code, agent workspaces            | `create()` from your code                          | One container per `create()`     |

Containers start when work arrives and
[stop when idle](/concepts/scaling#warm-containers), and every remote call is a
[task](/concepts/tasks-and-logs). A deploy starts every kind except sandboxes.

## Define an app

```python theme={null}
import urllib.request

from lazycloud import App
from pydantic import BaseModel

app = App("page_stats")


class PageStats(BaseModel):
    bytes: int
    words: int
    links: int


class AnalysisStarted(BaseModel):
    task_id: str


@app.function(cpu=1, memory="512Mi", timeout_seconds=120)
def analyze_page(url: str) -> PageStats:
    with urllib.request.urlopen(url, timeout=30) as response:
        html = response.read().decode("utf-8", errors="replace")
    return PageStats(bytes=len(html), words=len(html.split()), links=html.count("<a "))


@app.endpoint(name="analyze", methods=["POST"])
def analyze(url: str) -> AnalysisStarted:
    call = analyze_page.spawn(url)
    return AnalysisStarted(task_id=call.task_id)
```

The endpoint answers at once with a task ID, and `analyze_page` fetches the page
in its own cloud container, so a slow site never holds the request open.

App names use lowercase letters, digits, and underscores, start with a letter,
and run up to 63 characters. Workload names default to the Python name and are
unique per kind within an app. Values that change between workspaces live
outside the decorator, credentials in [secrets](/concepts/secrets) and files in
[volumes](/concepts/volumes).

## Deploy

```bash theme={null}
uv run lazycloud deploy page_stats            # every workload in the app
uv run lazycloud deploy page_stats:analyze    # just the endpoint
```

From Python, `app.deploy()` and `analyze.deploy()` do the same.
[Handler references](/cli/overview#handler-references) covers the syntax.

## Split an app across files

Each module imports the app and registers its own workloads:

```python theme={null}
# page_stats/app.py
from lazycloud import App

app = App("page_stats")
```

```python theme={null}
# page_stats/api.py
from page_stats.app import app
from page_stats.workers import AnalysisStarted, analyze_page


@app.endpoint(name="analyze", methods=["POST"])
def analyze(url: str) -> AnalysisStarted:
    return AnalysisStarted(task_id=analyze_page.spawn(url).task_id)
```

The CLI finds workloads by importing the module you name. `page_stats.api`
imports `page_stats.workers`, so it reaches both:

```bash theme={null}
uv run lazycloud deploy page_stats.api            # analyze and analyze_page
uv run lazycloud deploy page_stats.api:analyze    # just the endpoint
```

`page_stats.app` alone holds no workloads. When no module imports the rest, a
small entry module that imports each one does.

## Remove workloads

A workload deleted from the code stays deployed until a deploy with `--prune`:

```bash theme={null}
uv run lazycloud deploy page_stats --diff --prune   # preview
uv run lazycloud deploy page_stats --prune
```

Pruning stops every deployed workload the app no longer declares and removes
its schedules and routes. It needs the whole app, so a single-workload reference
can't prune. Volumes, secrets, and stored data stay, even when you delete the
whole app. From Python, `app.deploy(prune=True)`.

## Call deployed workloads from other projects

```bash theme={null}
uv run lazycloud app export page_stats
```

This writes a typed package to `lazycloud_clients/page_stats`, so another
project can call the deployed functions with `remote()` and the endpoints with
`request()`, without your source. ASGI routes get typed methods from the app's
OpenAPI schema, from `/openapi.json` unless `--openapi-path` or `--openapi`
points elsewhere.

The package holds no credentials, since callers sign in with `lazycloud login`.
Pods and sandboxes aren't exported, and a contract change needs a new export.

## Pause and delete

```bash theme={null}
uv run lazycloud app pause page_stats     # stop every workload, keep definitions
uv run lazycloud app resume page_stats
uv run lazycloud app delete page_stats
```

## Workspaces

A workspace holds apps, deployments, tasks, and stored data. Within it, a name
always means the same resource, so two apps mounting the `models` volume see
the same files. Separate projects, or staging and production, fit separate
workspaces. Tokens, a connected AWS account, joined machines, domains, and your
plan belong to your account and apply to every workspace you own.

```bash theme={null}
uv run lazycloud workspace list
uv run lazycloud workspace use staging
```

`LAZYCLOUD_WORKSPACE` overrides the stored choice for every command, which
suits CI, and `--workspace` overrides it for one.
[Compute](/platform/compute#where-a-workload-runs) covers where a workspace's
workloads run, and the [dashboard](/platform/dashboard#manage-access-and-compute)
covers members.
