Skip to main content

metaflow-prefect

CI PyPI License: Apache-2.0 Python 3.10+

Deploy and run Metaflow flows as Prefect deployments.

metaflow-prefect generates a self-contained Prefect flow file from any Metaflow flow, letting you schedule, deploy, and monitor your pipelines through Prefect while keeping all your existing Metaflow code unchanged.

Install

pip install metaflow-prefect

Or from source:

git clone https://github.com/npow/metaflow-prefect.git
cd metaflow-prefect
pip install -e ".[dev]"

Quick start

# Compile and run locally (no Prefect server needed)
python my_flow.py prefect run

# Register as a named deployment on a Prefect server
python my_flow.py prefect create --name prod --work-pool my-pool

Usage

Commands

Command Description
prefect run Compile and run the flow via Prefect locally (ephemeral, no server needed).
prefect resume --clone-run-id <id> Re-run a failed flow, skipping steps that already succeeded.
prefect compile <output.py> Write the generated Prefect flow file without running it.
prefect create --name <name> Register a named deployment on a running Prefect server.
prefect trigger --name <name> Trigger a run for an existing deployment.
# Run locally
python my_flow.py prefect run

# Resume a failed run (reuses already-completed step outputs)
python my_flow.py prefect resume --clone-run-id prefect-<uuid>

# Deploy to a Prefect server
python my_flow.py prefect create --name prod --work-pool my-pool

# Trigger a run of the deployed flow
python my_flow.py prefect trigger --name prod

All graph shapes are supported

# Linear
class SimpleFlow(FlowSpec):
    @step
    def start(self):
        self.value = 42
        self.next(self.end)
    @step
    def end(self): pass

# Split/join (static branch)
class BranchFlow(FlowSpec):
    @step
    def start(self):
        self.next(self.branch_a, self.branch_b)
    ...

# Conditional (dynamic branch — only one path runs at runtime)
class ConditionalFlow(FlowSpec):
    value = Parameter("value", default=42, type=int)
    @step
    def start(self):
        self.route = "high" if self.value >= 50 else "low"
        self.next({"high": self.high_branch, "low": self.low_branch}, condition="route")
    @step
    def high_branch(self): ...
    @step
    def low_branch(self): ...
    @step
    def join(self): ...

# Foreach fan-out (body tasks run concurrently)
class ForeachFlow(FlowSpec):
    @step
    def start(self):
        self.items = [1, 2, 3]
        self.next(self.process, foreach="items")
    ...

Parametrised flows

Parameters defined with metaflow.Parameter are forwarded automatically:

python param_flow.py prefect run
# Or pass parameters at the CLI:
python param_flow.py prefect compile param_flow_prefect.py
python param_flow_prefect.py --message "hello" --count 5

Step decorator support

@retry, @timeout, @environment, and @resources decorators are read from your flow and applied to the generated Prefect tasks automatically — no changes to your flow code required.

class MyFlow(FlowSpec):
    @retry(times=3, minutes_between_retries=2)
    @timeout(seconds=600)
    @environment(vars={"API_KEY": "secret"})
    @step
    def train(self):
        ...

The generated Prefect task becomes:

@task(name="train", retries=3, timeout_seconds=600, retry_delay_seconds=120)
def _step_train(run_id, prev_task_id):
    _extra_env.update({"API_KEY": "secret"})
    ...

Event-based triggers

@trigger and @trigger_on_finish are wired as Prefect automations when the deployment is registered. Re-running prefect create updates the automations in place.

@trigger_on_finish(flow="UpstreamFlow")
class MyFlow(FlowSpec):
    ...
python my_flow.py prefect create --name prod --work-pool my-pool
# → Registers deployment AND creates a Prefect automation:
#   "on prefect.flow-run.Completed for flow 'UpstreamFlow' → run deployment 'prod'"
@trigger(event="data.ready")
class MyFlow(FlowSpec):
    ...
python my_flow.py prefect create --name prod --work-pool my-pool
# → Registers deployment AND creates a Prefect automation:
#   "on event 'data.ready' → run deployment 'prod'"

Resume failed runs

Pass --clone-run-id to reuse outputs from steps that already succeeded in a previous run:

python my_flow.py prefect resume --clone-run-id prefect-<uuid-of-failed-run>

Configuration

Metadata service and datastore

By default, metaflow-prefect uses whatever metadata and datastore backends are active in your Metaflow environment. The generated Prefect file bakes in METADATA_TYPE and DATASTORE_TYPE at creation time so every step subprocess uses the same backend.

To use a remote metadata service or object store, configure them before running prefect create:

# Remote metadata service + S3 datastore
python my_flow.py \
  --metadata=service \
  --datastore=s3 \
  prefect create --name prod --work-pool my-pool

Or via environment variables (applied to all flows):

export METAFLOW_DEFAULT_METADATA=service
export METAFLOW_DEFAULT_DATASTORE=s3
python my_flow.py prefect create --name prod --work-pool my-pool

Flow-level timeout

python my_flow.py prefect create --name prod --workflow-timeout=3600

Step decorators (--with)

Inject Metaflow step decorators at deploy time without modifying the flow source:

# Run each step inside a sandbox (e.g. metaflow-sandbox extension)
python my_flow.py prefect run --with=sandbox

# Multiple decorators supported at deployment time
python my_flow.py prefect create --name prod \
  --with=sandbox \
  --with="resources:cpu=4,memory=8000"

@project support

Flows decorated with @project use a project-qualified name for the deployment:

@project(name="my-team")
class MyFlow(FlowSpec):
    ...
# Deployment will be registered as "my-team.MyFlow"
python my_flow.py prefect create --name prod

How it works

metaflow-prefect generates a self-contained Prefect flow file from your Metaflow flow's DAG. Each Metaflow step becomes a @task. The generated file:

  • runs each step as a subprocess via the standard metaflow step CLI
  • streams stdout and stderr from each step subprocess to the Prefect logger in real time
  • passes --input-paths correctly for joins and foreach splits
  • runs foreach body tasks concurrently via Prefect's task runner
  • maps @retry, @timeout, @environment, and @resources decorators to Prefect task settings
  • writes Metaflow artifacts to the Prefect UI as markdown artifacts with a ready-to-use retrieval snippet
  • creates Prefect automations for @trigger and @trigger_on_finish when deploying

Prefect UI: flow run timeline

The generated flow preserves the Metaflow DAG structure — foreach fan-outs appear as parallel task runs in the Prefect timeline:

Flow run timeline showing foreach fan-out

Prefect UI: artifact retrieval snippets

After each step completes, a Prefect artifact is posted showing the Metaflow self.* artifact names and a one-liner to fetch each value:

Artifact tab showing retrieval snippet

Supported decorators

Decorator Behaviour
@retry(times=N, minutes_between_retries=M) Maps to @task(retries=N, retry_delay_seconds=M*60)
@timeout(seconds=N) / @timeout(minutes=N) Maps to @task(timeout_seconds=N)
@environment(vars={...}) Merges vars into the step subprocess environment
@resources(cpu=N, gpu=G, memory=M) Added as Prefect task tags; GPU steps get a concurrency tag. Advisory only — configure matching resources on the work pool.
@schedule(cron=...) Used as the deployment cron schedule
@project(name=...) Prefixes the deployment name with the project name
@trigger(event=...) Creates a Prefect automation that fires the deployment on the named event
@trigger_on_finish(flow=...) Creates a Prefect automation that fires the deployment when the upstream Prefect flow completes

Unsupported decorators (@batch, @slurm, @exit_hook, @parallel) raise a clear error at compile time.

Limitations

Limitation Detail
No parallel_foreach parallel_foreach=True (Metaflow's MPI-style multi-node execution) requires @batch or @kubernetes backends and runs as a single distributed job, which has no Prefect equivalent. Raises an error at compile time.
@resources tags are advisory CPU/GPU/memory hints are added as Prefect task tags and are visible in the UI, but do not automatically allocate resources — configure matching resources on the work pool.
@trigger event scope @trigger(event="foo") watches for a Prefect event named "foo". Metaflow's own event system is separate from Prefect's — emit events via Prefect's event API to use this trigger.

Development

git clone https://github.com/npow/metaflow-prefect.git
cd metaflow-prefect
pip install -e ".[dev]"
pytest -v

License

Apache 2.0

Metadata

Release files for metaflow-prefect 0.3.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for metaflow-prefect 0.3.7
File Size Uploaded Provenance
metaflow_prefect-0.3.7.tar.gz 399.1 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for metaflow-prefect 0.3.7
File Interpreter ABI Platform
metaflow_prefect-0.3.7-py3-none-any.whl Python 3 none any Details

Total release size: 436.0 kB

Release files / metaflow_prefect-0.3.7.tar.gz

Download URL metaflow_prefect-0.3.7.tar.gz
Size 399.1 kB
Tags Source
SHA-256 checksum
How to use checksums
5eff877b93997984dbb98c695e25ff02e5ff5f4111ab8f5cf85f405d0230e8c2
BLAKE2b-256 checksum
How to use checksums
c458d18195c3212a492087c85aeb89ed04d347134e7cd70875db97b9b802b686
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 7, 2026.

Transparency log

Release files / metaflow_prefect-0.3.7-py3-none-any.whl

Download URL metaflow_prefect-0.3.7-py3-none-any.whl
Size 36.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
68ddf60bde2db2797c425b6ce2f441d8fc2a2ac3882a86f653caa7915e728eb0
BLAKE2b-256 checksum
How to use checksums
fbd1a0790a7b7e7810ac9c374dbdcd10aff28069f1a6c0dd950ad6f5cecef3d5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 7, 2026.

Transparency log

Security for metaflow-prefect 0.3.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for metaflow_prefect-0.3.7.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 7, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page