Kiran
10/09/2025, 6:32 AMMarvin
10/09/2025, 6:32 AMMarvin
10/09/2025, 6:35 AMrun_deployment(..., as_subflow=True), the UI will show them as child runs of the main flow run. You’ll see the parent/child relationship in the flow run page (Related runs and timeline). The UI does not currently draw explicit edges between sibling sub-deployments, but the parent-child lineage and execution order are visible.
How to do it
- Call each sub-deployment from your main flow with as_subflow=True (it’s the default in Prefect 3.x, but setting it explicitly is clear).
- Call them sequentially to enforce the order you want.
Example:
from prefect import flow
from prefect.deployments import run_deployment
@flow
def orchestrator():
# Step 1
fr1 = run_deployment(
"ingest/production",
parameters={"date": "2025-10-09"},
as_subflow=True,
flow_run_name="ingest-2025-10-09"
)
# Step 2 (runs after Step 1 completes)
fr2 = run_deployment(
"transform/production",
parameters={"date": "2025-10-09"},
as_subflow=True,
flow_run_name="transform-2025-10-09"
)
# Step 3
fr3 = run_deployment(
"load/production",
parameters={"date": "2025-10-09"},
as_subflow=True,
flow_run_name="load-2025-10-09"
)
What you’ll see in the UI
- On the orchestrator run page: a list of child runs (the three sub-deployments), plus a timeline showing their order.
- On each child run: a link back to its parent run.
- If you need a single DAG-like graph, consider modeling these as subflows/tasks within one flow (which is essentially what as_subflow=True gives you, but the graph between siblings is not drawn as edges).
Notes
- If you trigger deployments from outside a flow (e.g., with the API, CLI, or an Automation), there won’t be a parent-child link in the UI—use run_deployment from within a running flow to preserve lineage.
- You can improve readability with flow_run_name and tags.
Related references:
- Deployments API (3.x)
- Workflow design patterns blog
If you can share how you’re invoking the sub-deployments today (inside a flow with run_deployment vs. externally), I can suggest the exact pattern to get the lineage you want in the UI.Kiran
10/09/2025, 9:46 AMMarvin
10/09/2025, 9:46 AMMarvin
10/09/2025, 9:47 AMrun_deployment(..., as_subflow=True), the UI links runs through parent/child “Related runs,” but it won’t draw arrows between sibling sub-deployments on the timeline.
If you need true arrowed visualization between the sub-deployments:
- Model them as subflows/tasks within one orchestrator flow, pass results between them to create explicit edges in the Graph view.
- Or keep using deployments for isolation/infra and accept parent/child lineage without arrows on the timeline.
References:
- Deployments API (3.x)
- Workflow design patterns blog
If you describe the level of detail you want (task-level vs run-level) and whether you must keep separate deployments, I can suggest the exact pattern to get the clearest graph.Kiran
10/09/2025, 10:01 AMMarvin
10/09/2025, 10:01 AMMarvin
10/09/2025, 10:03 AMrun_deployment call in a small task and pass the previous task’s output into the next task. This creates explicit edges in the Graph of your main run.
- Use as_subflow=True so each stage also shows as a child run with lineage.
Example:
from prefect import flow, task
from prefect.deployments import run_deployment
@task
def trigger(deployment_name: str, params: dict | None = None, upstream_id: str | None = None):
# upstream_id is only to create a dependency edge; not used otherwise
fr = run_deployment(deployment_name, parameters=params, as_subflow=True)
return str(fr.id) # returning something lets the next call depend on this
@flow(name="prime-main-deployment")
def orchestrate():
s1 = trigger("get_json/production")
s2 = trigger("mainq1/production", upstream_id=s1)
s3 = trigger("mainq2/production", upstream_id=s2)
s4 = trigger("client/production", upstream_id=s3)
What you’ll see:
- In the Graph tab of the main run: arrows s1 → s2 → s3 → s4.
- Each node corresponds to the “trigger” task; each also creates a linked child run (the actual deployment) you can click into.
Behavior notes:
- run_deployment(..., as_subflow=True) links the child run to the parent and waits for it to finish before continuing. If a stage fails, the main flow will stop and downstream stages won’t start.
B) If you can call flows directly (not via deployments)
- Import the underlying flows and call them as subflows, passing each result to the next. This gives very clean arrows between subflow nodes in the Graph.
- Tradeoff: they’ll run on the orchestrator’s infra, not the infra attached to each deployment.
Docs/refs:
- Run deployments from flows (3.x)
- Workflow design patterns blog
If you want, share the names/parameters for each deployment and I’ll tailor the orchestrator snippet exactly to your setup.Kiran
10/09/2025, 10:25 AMMarvin
10/09/2025, 10:25 AMMarvin
10/09/2025, 10:26 AMrun_deployment call in a Prefect task and pass the previous task’s result into the next task. That creates explicit upstream/downstream edges in the Graph tab of your main run.
Here’s a cleaned-up version of your flow that does exactly that:
from prefect import flow, task
from prefect.deployments import run_deployment
from prefect.client.schemas.objects import StateType
import asyncio
# Each stage is a task; passing the previous stage's result creates edges in the Graph
@task(name="get_json")
async def run_get_json():
fr = await run_deployment(
name="get-json-flow/getjson_prime_deployment",
job_variables={"cpu": 256, "memory": 1024},
as_subflow=True,
flow_run_name="get_json",
)
return fr.id # returning something to wire dependencies downstream
@task(name="mainq1")
async def run_mainq1(prev_id: str):
fr = await run_deployment(
name="mainq1-flow/mainq1_latest_deployment",
job_variables={"cpu": 256, "memory": 1024},
as_subflow=True,
flow_run_name="mainq1",
)
return fr.id
@task(name="mainq2")
async def run_mainq2(prev_id: str):
fr = await run_deployment(
name="mainq2/mainq2_latest_deployment",
job_variables={"cpu": 256, "memory": 1024},
as_subflow=True,
flow_run_name="mainq2",
)
return fr.id
@task(name="client")
async def run_client(prev_id: str, client: str, tasks: list[list[str]]):
fr = await run_deployment(
name="client-flow/client_latest_deployment",
parameters={"client": client, "tasks": tasks},
job_variables={"cpu": 256, "memory": 1024},
as_subflow=True,
flow_run_name=client,
)
return fr.id
@flow(log_prints=True, name="prime-main-deployment")
async def prime_main_flow():
# Stage 1
s1 = await run_get_json()
# Stage 2 (runs after Stage 1 completes)
s2 = await run_mainq1(s1)
# Stage 3 (runs after Stage 2 completes)
s3 = await run_mainq2(s2)
# Optional fan-out to multiple clients AFTER mainq2
clients = {
"client_1": [["PS_Extend_General_PSwaps", "PS_TPLSweep_General_PSwaps"], ["PS_Generate", "PS_MTM", "PS_Sweeping"], ["PS_LoanAccountSweeper"], ["PS_Reporting"]],
"client_2": [["PS_Extend_General_PSwaps", "PS_TPLSweep_General_PSwaps"], ["PS_Generate", "PS_MTM", "PS_Sweeping"], ["PS_LoanAccountSweeper"], ["PS_Reporting"]],
# add more clients...
}
# Run client deployments concurrently, but each depends on mainq2
await asyncio.gather(
*[run_client(s3, client=c, tasks=clients[c]) for c in clients]
)
Why this creates arrows in the Graph
- Each deployment trigger is a Prefect task node.
- Passing the previous task’s output (even if unused) to the next creates explicit dependencies: get_json → mainq1 → mainq2 → client.
- With as_subflow=True, each task also creates a linked child run (clickable in the UI under Related runs).
Notes
- run_deployment(..., as_subflow=True) waits for the child run to finish; if a stage fails, the flow will stop and downstream nodes won’t run.
- Prefer comparing states using the enum (e.g., StateType.COMPLETED) if you branch by state; however, the chain above enforces order without manual state checks.
- The timeline view still won’t draw arrows; use the Graph tab on the main run to see the chain.
Docs for reference:
- Run deployments from flows (3.x)
If you share the exact deployment names/parameters you need, I can drop them into this template verbatim.