Hello <@ULVA73B9P> ! I'm trying to schedule an exi...
# ask-marvin
a
Hello @Marvin ! I'm trying to schedule an existing deployment from Python code but for a single date (it needs to be run only one time, I let my flow auto reschedule). How to do that?
m
thought for 77.8 seconds
Yes — for a single future run of an existing deployment, the simplest approach in Prefect 3.x is to create a flow run from the deployment with a
scheduled_time
. Use
run_deployment()
from Python:
Copy code
python
from datetime import datetime, timezone
from prefect.deployments import run_deployment

flow_run = run_deployment(
    name="my-flow/my-deployment",
    scheduled_time=datetime(2026, 6, 10, 14, 0, tzinfo=timezone.utc),
    timeout=0,  # don't wait for completion
)

print(flow_run.id)
A few notes: -
name
should be
"flow_name/deployment_name"
or the deployment ID -
scheduled_time
is the one-time execution date -
timeout=0
makes this return immediately after creating the scheduled run If you want to pass parameters too:
Copy code
python
from datetime import datetime, timezone
from prefect.deployments import run_deployment

flow_run = run_deployment(
    name="my-flow/my-deployment",
    scheduled_time=datetime(2026, 6, 10, 14, 0, tzinfo=timezone.utc),
    parameters={"x": 123},
    timeout=0,
)
Important: You do not need to add a deployment schedule for this. Deployment schedules are for recurring runs. For a one-off run, just create a scheduled flow run like above. If you're in async code, use
arun_deployment()
instead:
Copy code
python
from datetime import datetime, timezone
from prefect.deployments import arun_deployment

flow_run = await arun_deployment(
    name="my-flow/my-deployment",
    scheduled_time=datetime(2026, 6, 10, 14, 0, tzinfo=timezone.utc),
    timeout=0,
)
Relevant docs/source: - `run_deployment` API - Deployments concept docs If you want, I can also show the lower-level client version (
create_flow_run_from_deployment
) in case you're already using
get_client()
.
a
@Marvin Should I use the as_subflow ?
m
thought for 11.2 seconds
No — not for this use case.
as_subflow
is for when one flow run creates another flow run as a child/subflow relationship. That’s useful for orchestration lineage, but it is not what you want for “schedule this deployment once at a given date”. For a one-time future run of an existing deployment, just do:
Copy code
python
from datetime import datetime, timezone
from prefect.deployments import run_deployment

run_deployment(
    name="my-flow/my-deployment",
    scheduled_time=datetime(2026, 6, 10, 14, 0, tzinfo=timezone.utc),
    timeout=0,
)
Use
as_subflow=True
only if: - you are inside another running flow - and you intentionally want the created deployment run to be tracked as a subflow of that parent flow For your case — “run this deployment one time in the future, and let the flow handle its own rescheduling logic afterward” — leave
as_subflow
alone
. If you want, I can explain the exact behavioral difference between: -
run_deployment(...)
-
run_deployment(..., as_subflow=True)
- calling a flow directly as a subflow
a
I can't see the scheduled deploymennt in the dashboard @Marvin
m
thought for 144.0 seconds
That’s expected in many cases: a one-off run created with
run_deployment(..., scheduled_time=...)
is not a deployment schedule. It creates a scheduled flow run. So in the UI, you should look for it under: - Flow Runs - or the specific deployment’s Runs tab not under: - Schedules for the deployment A few things to check: 1. Confirm the flow run was actually created Capture and print the returned object:
Copy code
python
from datetime import datetime, timezone
from prefect.deployments import run_deployment

flow_run = run_deployment(
    name="my-flow/my-deployment",
    scheduled_time=datetime(2026, 6, 10, 14, 0, tzinfo=timezone.utc),
    timeout=0,
)

print(flow_run.id)
print(flow_run.state_type)
print(flow_run.state_name)
You should get a flow run ID and a state like
SCHEDULED
. 2. Check the Deployment’s Runs tab, not Schedules This run is a manually created scheduled run, so it usually won’t show up as a schedule definition. 3. Check UI filters If your dashboard is filtered to only show: - running - recent - today - a specific work pool/work queue then a future scheduled run may be hidden. Look for filters around: - state =
Scheduled
- expected start time / time range - all runs instead of just active/recent runs 4. Make sure the scheduled time is timezone-aware and in the future If the timestamp is naive or unexpectedly converted, it may not land where you expect in the UI. Safer pattern:
Copy code
python
from datetime import datetime, timezone

scheduled_time = datetime(2026, 6, 10, 14, 0, tzinfo=timezone.utc)
5. Verify you’re looking in the same workspace / profile This sounds obvious, but it’s a common cause if the code is pointed at a different API URL or workspace than the dashboard you’re viewing. You can also verify it programmatically with the client:
Copy code
python
from prefect import get_client
import asyncio

FLOW_RUN_ID = "your-flow-run-id"

async def main():
    async with get_client() as client:
        flow_run = await client.read_flow_run(FLOW_RUN_ID)
        print(flow_run.id)
        print(flow_run.state_type)
        print(flow_run.state_name)
        print(flow_run.expected_start_time)

asyncio.run(main())
If that returns the run, then it exists and the issue is just where/filtering in the UI. Most likely answer: you’re checking the deployment Schedules area, but this one-time future execution is a scheduled flow run, not a deployment schedule. Docs: - `run_deployment` API - Deployments docs If you want, I can give you a tiny snippet to list all scheduled flow runs for a deployment so you can confirm it from Python.
a
Also, how to check if a deployment has been run by a schedule or manually @Marvin?
m
thought for 140.5 seconds
Yes — you can check this on the flow run, not on the deployment itself. The two most useful fields are: -
auto_scheduled
-
created_by
Rules of thumb: - Deployment schedule run
auto_scheduled == True
and usually
created_by.type == "SCHEDULE"
- Manual run (UI/API/`run_deployment(...)`) → usually
auto_scheduled == False
and
created_by is None
Example:
Copy code
python
import asyncio
from prefect import get_client

FLOW_RUN_ID = "your-flow-run-id"

async def main():
    async with get_client() as client:
        flow_run = await client.read_flow_run(FLOW_RUN_ID)

        print("auto_scheduled:", flow_run.auto_scheduled)
        print("created_by:", flow_run.created_by)

        if flow_run.created_by and flow_run.created_by.type == "SCHEDULE":
            print("Run was created by a deployment schedule")
        elif flow_run.created_by is None:
            print("Run was created manually")
        else:
            print(f"Run was created by: {flow_run.created_by.type}")

asyncio.run(main())
If you want the shortest test:
Copy code
python
is_schedule_run = (
    flow_run.created_by is not None
    and flow_run.created_by.type == "SCHEDULE"
)
You can also inspect tags — scheduled deployment runs get an
auto-scheduled
tag — but
created_by
is the cleaner signal. So for your earlier one-time run created with:
Copy code
python
run_deployment(..., scheduled_time=...)
that is typically manual, not a deployment-schedule run: -
auto_scheduled = False
-
created_by = None
because you created a scheduled flow run, not a deployment schedule. Relevant docs: - Client schema objects - `run_deployment` API If you want, I can also give you a snippet to list all runs for a deployment and split them into scheduled-vs-manual.