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

# Deploying apps in flows

## `@app_deploy`

Simplify bookkeeping and lifecycle management for apps deployed from Metaflow flows.

While you can deploy apps from within a flow using the `AppDeployer` API directly,
doing so at scale introduces operational challenges: tracking which apps belong to
which run, cleaning up apps when flows complete or fail, and discovering apps
deployed across many runs. This decorator addresses these concerns automatically.

When applied to a flow, `@app_deploy` provides:

1. **Automatic Tagging**: Every app deployed gains Metaflow metadata tags
   (flow name, run ID, step, task ID, project/branch info) enabling easy
   discovery and association with specific flow executions.

2. **Lifecycle Management**: Configure automatic cleanup policies to scale down
   or delete apps when the flow exits (on success or failure), preventing
   orphaned apps from accumulating.

3. **Convenient Access**: Exposes `current.apps` with the flow's code package
   and container image, plus a `list()` method to discover all apps deployed
   in the current run.

**Parameters:**

<ParamField path="cleanup_policy" type="string" default="none">
  Action to perform on all apps deployed in this run when the flow exits:

  * `"none"`: No cleanup; apps remain running after flow completion.
  * `"scale_down"`: Scale all deployed apps to zero replicas.
  * `"delete"`: Delete all deployed apps.
</ParamField>

**Examples:**

```python expandable theme={null}
from metaflow import FlowSpec, step, current, app_deploy
from metaflow.apps import AppDeployer

@app_deploy
class MyFlow(FlowSpec):

    @step
    def start(self):
        # Deploy an app using the flow's code package
        deployer = AppDeployer(
            name="my-service",
            port=8000,
            image=current.apps.current_image,
            code_package=current.apps.metaflow_code_package,
            commands=["python server.py"],
        )
        self.app = deployer.deploy()
        self.next(self.end)

    @step
    def end(self):
        # List all apps deployed in this run
        apps = current.apps.list()
        print(f"Deployed {len(apps)} app(s)")
```

With cleanup policy to prevent orphaned apps:

```python theme={null}
@app_deploy(cleanup_policy="scale_down")
class MyFlow(FlowSpec):
    # Apps will be scaled to zero when flow completes or fails,
    # preventing resource waste from forgotten deployments
    ...
```

## `current.apps`

Manager for apps deployed within a Metaflow flow execution.

Accessible via `current.apps` when using the `@app_deploy` decorator.
Provides access to the flow's code package, container image, and
methods to list apps deployed in the current run.

**Attributes:**

<ParamField path="metaflow_code_package" type="object">
  The code package for the current flow, ready to use with `AppDeployer`.
</ParamField>

<ParamField path="current_image" type="string">
  The container image used by the current task (from fast bakery or similar).
</ParamField>

<ParamField path="default_image" type="string">
  The default Kubernetes container image from the Metaflow config.
</ParamField>

**Examples:**

```python expandable theme={null}
# python myflow.py --environment=fast-bakery run --with kubernetes
from metaflow.apps import AppDeployer

@pypi(packages={"flask": ">=2.0", "requests": ">=2.28"})
@step
def deploy_step(self):
    image = current.apps.current_image
    if image is None:
        image = current.apps.default_image
    # Use the flow's code package directly
    deployer = AppDeployer(
        name="my-app",
        port=8000,
        image=image,
        code_package=current.apps.metaflow_code_package,
        commands=["python app.py"],
    )
    deployed = deployer.deploy()

    # List apps from this run
    apps = current.apps.list()
```
