> ## Documentation Index
> Fetch the complete documentation index at: https://prefect-bd373955-pytest-markdown.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy flows

> Learn how to configure flows for scheduled and remote execution.

[Deployments](/3.0rc/deploy/serve-flows/) are server-side representations of flows.
They store the crucial metadata for remote orchestration including when, where, and
how a workflow should run.

Attributes of a deployment include:

* **Flow entrypoint**: path to your flow function
* **Schedule** or **Trigger**: optional schedule or triggering rules for this deployment
* **Tags**: optional text labels for organizing deployments

Some of the most common reasons to use an orchestration tool like Prefect are for
[scheduling](/3.0rc/automate/add-schedules/) and [event-based triggering](/3.0rc/automate/events/automations-triggers/).
As opposed to manually triggering and managing flow runs, deploying a flow exposes an API and
UI that allow you to:

* trigger new runs, [cancel active runs](/3.0rc/develop/write-flows/#cancel-a-flow-run),
  pause scheduled runs, customize parameters, and more
* remotely configure schedules and automation rules for your deployments
* dynamically provision infrastructure using [workers](/3.0rc/tutorials/workers/)

<Note>
  **Connect to Prefect Cloud or a self-hosted Prefect server instance**

  Some features in this tutorial, such as scheduling, require you to connect to a Prefect server.
  If using a self-hosted setup, run `prefect server start` to run both the webserver and UI.
  If using Prefect Cloud, make sure you have
  [successfully authenticated your local environment](/3.0rc/manage/cloud/connect-to-cloud).
</Note>

## Create a deployment

Here's an example of creating a deployment by calling a
single method on the flow object: `flow.serve`.

```python repo_info.py
import httpx
from prefect import flow


@flow(log_prints=True)
def get_repo_info(repo_name: str = "PrefectHQ/prefect"):
    url = f"https://api.github.com/repos/{repo_name}"
    response = httpx.get(url)
    response.raise_for_status()
    repo = response.json()
    print(f"{repo_name} repository statistics 🤓:")
    print(f"Stars 🌠 : {repo['stargazers_count']}")
    print(f"Forks 🍴 : {repo['forks_count']}")


if __name__ == "__main__":
    get_repo_info.serve(name="my-first-deployment")
```

Running this script will:

* create a deployment called `my-first-deployment` for your flow in the Prefect API
* continue running to listen for flow runs for this deployment; when a run is found, it\
  *asynchronously executes within a subprocess*

<Warning>
  **You must define deployments in static files**

  You can define and run flows interactively, within REPLs or Notebooks.
  However, deployments require that your flow definition exist in a known file.
</Warning>

Because this deployment doesn't have a schedule or triggering automation, you must use the UI or API to create
runs for it.
Use the CLI (in a separate terminal window) to create a run for this deployment:

```bash
prefect deployment run 'get-repo-info/my-first-deployment'
```

In your terminal or UI, you should see the newly created run execute successfully.

### Additional options

The `serve` method on flows exposes many options for the deployment. For more information, see
[Serve a flow](3.0rc/deploy/serve-flows/serve-a-flow)
Here's how to use some of those options:

* `cron`: a keyword that allows you to set a cron string schedule for the deployment; see
  [schedules](/3.0rc/automate/add-schedules/) for more advanced scheduling options
* `tags`: a keyword that allows you to tag this deployment and its runs for bookkeeping and filtering purposes
* `description`: a keyword that allows you to document what this deployment does; by default the
  description is set from the docstring of the flow function (if documented)
* `version`: a keyword that allows you to track changes to your deployment; uses a hash of the
  file containing the flow by default; popular options include semver tags or git commit hashes

Next, add these options to your deployment:

```python
if __name__ == "__main__":
    get_repo_info.serve(
        name="my-first-deployment",
        cron="* * * * *",
        tags=["testing", "tutorial"],
        description="Given a GitHub repository, logs repository statistics for that repo.",
        version="tutorial/deployments",
    )
```

When you rerun this script, you will find an updated deployment in the UI that is actively scheduling work.\
Stop the script in the CLI using `CTRL+C` and your schedule automatically pauses.

<Note>
  **`.serve` is a long-running process**

  To execute remotely triggered or scheduled runs, your script with `flow.serve` must be actively running.
</Note>

## Run multiple deployments at once

This method is useful for creating deployments for single flows. For two or more flows, you must provide a
few additional method calls and imports:

```python multi_flow_deployment.py
import time
from prefect import flow, serve


@flow
def slow_flow(sleep: int = 60):
    "Sleepy flow - sleeps the provided amount of time (in seconds)."
    time.sleep(sleep)


@flow
def fast_flow():
    "Fastest flow this side of the Mississippi."
    return


if __name__ == "__main__":
    slow_deploy = slow_flow.to_deployment(name="sleeper", interval=45)
    fast_deploy = fast_flow.to_deployment(name="fast")
    serve(slow_deploy, fast_deploy)
```

A few things to note:

* the `flow.to_deployment` interface exposes the *exact same* options as `flow.serve`; this method
  produces a deployment object
* the deployments are only registered with the API once `serve(...)` is called
* when serving multiple deployments, the only requirement is that they share a Python environment;
  they can be executed and scheduled independently of each other

A few optional steps for exploration include:

* pause and unpause the schedule for the "sleeper" deployment
* use the UI to submit ad-hoc runs for the "sleeper" deployment with different values for `sleep`
* cancel an active run for the "sleeper" deployment from the UI

<Tip>
  **Hybrid execution option**

  Prefect's deployment interface allows you to choose a hybrid execution model.
  Whether you use Prefect Cloud or host a Prefect server instance, you can run workflows in the
  environments best suited to their execution.
  This model enables efficient use of your infrastructure resources while maintaining the privacy
  of your code and data.
  There is no ingress required.
  Read more about our [hybrid model](https://www.prefect.io/security/overview/#hybrid-model).
</Tip>

## Deployment schema

Here's the complete schema that defines a deployment:

```python
class Deployment:
    """
    Structure of the schema defining a deployment
    """

    # required defining data
    name: str 
    flow_id: UUID
    entrypoint: str
    path: Optional[str] = None

    # workflow scheduling and parametrization
    parameters: Optional[Dict[str, Any]] = None
    parameter_openapi_schema: Optional[Dict[str, Any]] = None
    schedules: list[Schedule] = None
    paused: bool = False
    trigger: Trigger = None

    # metadata for bookkeeping
    version: Optional[str] = None
    description: Optional[str] = None
    tags: Optional[list] = None

    # worker-specific fields
    work_pool_name: Optional[str] = None
    work_queue_name: Optional[str] = None
    infra_overrides: Optional[Dict[str, Any]] = None
    pull_steps: Optional[Dict[str, Any]] = None
```

All methods for creating Prefect deployments are interfaces for populating this schema.
The following sections explain each component in more detail.

### Required data

Deployments universally require a `name` and a reference to an underlying `Flow`.

The deployment name is not required to be unique across all deployments, but is required to be unique
for a given flow ID. This means you will often see references to the deployment's unique identifying name
`{FLOW_NAME}/{DEPLOYMENT_NAME}`.

For example, triggering a run of a deployment from the Prefect CLI can be done with:

<div class="terminal">
  ```bash
  prefect deployment run my-first-flow/my-first-deployment
  ```
</div>

The other two fields are:

* **`path`**: think of the path as the runtime working directory for the flow.
  For example, if a deployment references a workflow defined within a Docker image, the `path` is the\
  absolute path to the parent directory where that workflow will run anytime the deployment is triggered.
  This interpretation is more subtle in the case of flows defined in remote filesystems.
* **`entrypoint`**: the entrypoint of a deployment is a relative reference to a function decorated as a
  flow that exists on some filesystem. It is always specified relative to the `path`.
  Entrypoints use Python's standard path-to-object syntax
  (for example, `path/to/file.py:function_name` or simply `path:object`).

The entrypoint must reference the same flow as the flow ID.

Prefect requires that deployments reference flows defined *within Python files*.
Flows defined within interactive REPLs or notebooks cannot currently be deployed as such.
They are still valid flows that will be monitored by the API and observable in the UI whenever they are run,
but Prefect cannot trigger them.

<Note>
  **Deployments do not contain code definitions**

  Deployment metadata references code that exists in potentially diverse locations within your environment.
  This separation means that your flow code stays within your storage and execution
  infrastructure, and never lives on the Prefect server or database.

  This is key to the Prefect hybrid model: there's a boundary between your proprietary assets,
  such as your flow code, and the Prefect backend (including [Prefect Cloud](/3.0rc/manage/cloud/)).
</Note>

### Scheduling and parametrization

One of the primary motivations for creating deployments of flows is to remotely *schedule* and *trigger* them.
Just as you can call flows as functions with different input values, deployments can be triggered or
scheduled with different values through parameters.

These are the fields to capture the required metadata for those actions:

* **`schedules`**: a list of [schedule objects](/3.0rc/automate/add-schedules/).
  Most of the convenient interfaces for creating deployments allow users to avoid creating this object themselves.
  For example, when [updating a deployment schedule in the UI](/3.0rc/automate/add-schedules/#creating-schedules-through-the-ui)
  basic information such as a cron string or interval is all that's required.
* **`trigger`** (Cloud-only): triggers allow you to define event-based rules for running a deployment.
  For more information see [Automations](/3.0rc/automate/events/automations-triggers/).
* **`parameter_openapi_schema`**: an [OpenAPI compatible schema](https://swagger.io/specification/) that defines
  the types and defaults for the flow's parameters.
  This is used by the UI and the backend to expose options for creating manual runs as well as type validation.
* **`parameters`**: default values of flow parameters that this deployment will pass on each run.
  These can be overwritten through a trigger or when manually creating a custom run.
* **`enforce_parameter_schema`**: a boolean flag that determines whether the API should validate the parameters
  passed to a flow run against the schema defined by `parameter_openapi_schema`.

<Tip>
  **Scheduling is asynchronous and decoupled**

  Pausing a schedule, updating your deployment, and other actions reset your auto-scheduled runs.
</Tip>

#### Run a deployed flow from within Python flow code

Prefect provides a [`run_deployment` function](/3.0rc/api-ref/prefect/deployments/deployments/#prefect.deployments.deployments.run_deployment)
to schedule the run of an existing deployment when your Python code executes.

```python
from prefect.deployments import run_deployment

def main():
    run_deployment(name="my_flow_name/my_deployment_name")
```

<Tip>
  **Run a deployment without blocking**

  By default, `run_deployment` blocks until the scheduled flow run finishes
  executing. Pass `timeout=0` to return immediately and not block.
</Tip>

If you call `run_deployment` from within a flow or task, the scheduled flow
run is linked to the calling flow run (or the calling task's flow run)
as a subflow run by default.

Subflow runs have different behavior than regular flow runs. For example, you can't suspend a
subflow run independently of its parent flow. To not link the scheduled flow run to the
calling flow or task run, pass `as_subflow=False` to disable it:

```python
from prefect import flow
from prefect.deployments import run_deployment


@flow
def my_flow():
    # The scheduled flow run will not be linked to this flow as a subflow.
    run_deployment(name="my_other_flow/my_deployment_name", as_subflow=False)
```

The return value of `run_deployment` is a [FlowRun](/3.0rc/api-ref/prefect/client/schemas/#prefect.client.schemas.objects.FlowRun)
object containing metadata about the scheduled run. Use this object to retrieve information
about the run after calling
`run_deployment`:

```python
from prefect import get_client
from prefect.deployments import run_deployment

def main():
    flow_run = run_deployment(name="my_flow_name/my_deployment_name")
    flow_run_id = flow_run.id

    # If you save the flow run's ID, you can use it later to retrieve
    # flow run metadata again, e.g. to check if it's completed.
    async with get_client() as client:
        flow_run = client.read_flow_run(flow_run_id)
        print(f"Current state of the flow run: {flow_run.state}")
```

<Tip>
  **Using the Prefect client**

  For more information on using the Prefect client to interact with Prefect's
  REST API, see [Interact with the API](/3.0rc/manage/interact-with-api/).
</Tip>

## Versioning and bookkeeping

Here is important information on the versions, descriptions, and tags fields:

* **`version`**: versions are always set by the client and can be any arbitrary string.
  We recommend tightly coupling this field on your deployments to your software development lifecycle.
  For example if you leverage `git` to manage code changes, use either a tag or commit hash in this field.
  If you don't set a value for the version, Prefect will compute a hash.
* **`description`**: provide reference material such as intended use and parameter documentation.
  Markdown is accepted. The docstring of your flow function is the default value.
* **`tags`**: group related work together across a diverse set of objects.
  Tags set on a deployment are inherited by that deployment's flow runs. Filter, customize views, and
  searching by tag.

<Tip>
  **Everything has a version**

  Deployments have a version attached; and flows and tasks also have
  versions set through their respective decorators. These versions are sent to the API
  anytime the flow or task runs, allowing you to audit changes.
</Tip>

### Workers and work pools

[Workers and work pools](/3.0rc/deploy/work-pools/control-runs/) are an advanced deployment pattern that
allow you to dynamically provision infrastructure for each flow run.
The work pool job template interface allows users to create and govern opinionated interfaces
to their workflow infrastructure.
To do this, a deployment using workers needs the following fields:

* **`work_pool_name`**: the name of the work pool this deployment is associated with.
  Work pool types mirror infrastructure types, which means this field impacts the options available
  for the other fields.
* **`work_queue_name`**: if you are using work queues to either manage priority or concurrency, you can
  associate a deployment with a specific queue within a work pool using this field.
* **`infra_overrides`**: often called `job_variables` within various interfaces, this field allows
  deployment authors to customize whatever infrastructure options have been exposed on this work pool.
  This field is often used for Docker image names, Kubernetes annotations and limits,
  and environment variables.
* **`pull_steps`**: a JSON description of steps that retrieves flow code or
  configuration, and prepares the runtime environment for workflow execution.

Pull steps allow users to highly decouple their workflow architecture.
For example, a common use of pull steps is to dynamically pull code from remote filesystems such as
GitHub with each run of their deployment.

### Serving flows on long-lived infrastructure

When you have several flows running regularly, [the `serve` method](/3.0rc/develop/write-flows/#serving-a-flow)
of the `Flow` object or [the `serve` utility](/3.0rc/develop/write-flows/#serving-multiple-flows-at-once)
is a great option for managing multiple flows simultaneously.

Once you have authored your flow and decided on its deployment settings, run this long-running
process in a location of your choosing.
The process stays in communication with the Prefect API, monitoring for work and submitting each run
within an individual subprocess.
Because runs are submitted to subprocesses, any external infrastructure configuration
must be set up beforehand and kept associated with this process.

This approach has these benefits:

* Users are in complete control of their infrastructure, and anywhere the "serve" Python process can
  run is a suitable deployment environment.
* It is simple to reason about.
* Creating deployments requires a minimal set of decisions.
* Iteration speed is fast.

### Dynamically provisioning infrastructure with work pools

Consider running flows on dynamically provisioned
infrastructure with work pools under these circumstances:

* Flows that have expensive infrastructure due to the long-running process.
* Flows with heterogeneous infrastructure needs across runs.
* Large volumes of deployments.
* If your internal team structure requires that deployment authors be members of a different team
  than the team managing infrastructure.

[Work pools](/3.0rc/deploy/work-pools/control-runs/) allow Prefect to exercise greater control
of the infrastructure on which flows run.
Options for [serverless work pools](/3.0rc/deploy/dynamic-infra/push-runs-remote/) allow you to
scale to zero when workflows aren't running.
Prefect even provides you with the ability to
[provision cloud infrastructure via a single CLI command](/3.0rc/deploy/dynamic-infra/push-runs-serverless/#automatically-creating-a-new-push-work-pool-and-provisioning-infrastructure),
if you use a Prefect Cloud push work pool option.

With work pools:

* You can configure and monitor infrastructure configuration within the Prefect UI.
* Infrastructure is ephemeral and dynamically provisioned.
* Prefect is more infrastructure-aware and collects more event data from your infrastructure by default.
* Highly decoupled setups are possible.

<Note>
  **You don't have to commit to one approach**

  You can mix and match approaches based on the needs of each flow. You can also change the
  deployment approach for a particular flow as its needs evolve.
  For example, you might use workers for your expensive machine learning pipelines,
  but use the serve mechanics for smaller, more frequent file-processing pipelines.
</Note>
