Kiran
09/10/2025, 6:19 AMMarvin
09/10/2025, 6:19 AMMarvin
09/10/2025, 6:23 AMrun_deployment
many times.
Likely causes
- Parent flow (or the function wrapping the loop) retried/restarted: If your parent flow has retries, was manually retried in the UI, or crashed/restarted, the loop will re-execute and call run_deployment
again for the same items. Without idempotency, that creates duplicate subflow runs.
- A task with retries wrapping `run_deployment`: If you call run_deployment
inside a @task(retries=...)
, each retry will call it again and create another subflow run unless you use an idempotency key.
- Transient network/error handling: If your code or environment retries a failed call after the request reached the Prefect API, it can produce duplicates unless you use idempotency.
- Input duplication: The config may contain duplicate entries (or be read/processed more than once) leading to the same “task name” being triggered multiple times.
How to make each item trigger exactly one subflow
- Use idempotency_key
for every run_deployment
call. Make it a deterministic key per work item (e.g., a stable item ID or a hash of the task name + config version). The API will ensure only one run is created for a given deployment+key.
- Ensure the code that calls run_deployment
is not wrapped in a retried task (or set retries=0 there), or rely on idempotency keys if it must be retried.
- If your parent flow itself has retries, idempotency keys still protect you.
Example pattern
from prefect import flow, get_run_logger
from prefect.deployments import run_deployment
import hashlib
def make_key(name: str, batch_id: str) -> str:
return hashlib.sha256(f"{batch_id}|{name}".encode()).hexdigest()
@flow
def parent_flow(config: dict, batch_id: str):
logger = get_run_logger()
for item in config["tasks"]:
name = item["name"]
key = make_key(name, batch_id)
fr = run_deployment(
name="my-subflow-deployment",
parameters=item,
flow_run_name=f"sub-{name}",
idempotency_key=key,
as_subflow=True, # default True; keeps linkage in the UI
)
<http://logger.info|logger.info>(f"Triggered subflow for {name}: {fr.id}")
How to diagnose your current run
- Check the parent flow run timeline/logs for “Retrying…” or “Resuming flow run…” messages.
- Confirm whether the call to run_deployment
is inside any @task
with retries.
- Compare duplicate subflow runs’ parameters and names; if they match exactly, it’s very often a retry/restart scenario without idempotency.
References
- API: Create flow run from deployment (supports idempotency_key
): Create flow run from deployment (3.x)
- Why idempotency matters: The importance of idempotent data pipelines
- Design patterns: Workflow design patterns
A few clarifying questions to help pinpoint the root cause:
- Which Prefect version are you on? (Assuming 3.x unless you say otherwise.)
- Is your parent flow configured with retries
? Did you manually retry or observe a crash/restart?
- Is run_deployment
called directly in the flow body, or inside a @task
that has retries?
- Are you currently setting idempotency_key
on run_deployment
? If so, how is it generated?
- Could you share a minimal snippet of the loop that triggers the subflows?
If you share your loop code and whether the parent retried, I can help you add a robust idempotency key and get you back to exactly 1 subflow per work item.