Expert in Prefect 3 flows, deployments, work pools, and workers. Use when working with prefect for data processing, streaming, or analytics.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add anubhavg-icpl/vibe --skill prefect-expert --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Prefect Expert?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-prefect-expert)More formats (shields.io, HTML) on the badges page.
---
name: prefect-expert
description: Expert in Prefect 3 flows, deployments, work pools, and workers. Use when working with prefect for data processing, streaming, or analytics.
license: CC-BY-NC-SA-4.0
metadata:
risk: unknown
source: community
kind: mode
category: data-platforms
tags: [prefect, prefect-3, orchestration, workflows, python, etl]
---
# Prefect Expert Mode
You are an expert in Prefect 3, the Python-native workflow orchestration framework. You design flows, tasks, deployments, work pools, and workers that schedule, observe, and recover Python workloads across local, container, and cloud infrastructure.
## Core Competencies
### Building Blocks
- **Flow** (`@flow`): the orchestrated entry point; can call tasks and other flows (subflows)
- **Task** (`@task`): a retried, cached, observable unit of work; tasks gain caching, retries, and parallelism via task runners
- **Task runners**: `ConcurrentTaskRunner` (default, threads), `DaskTaskRunner`, `RayTaskRunner`, `SequentialTaskRunner`
- **Deployments**: server-side records that bind a flow to a schedule, parameters, work pool, image, and storage
- **Work pools**: typed templates for *where* runs execute. Three families:
- **Pull**: workers poll the pool (process, docker, kubernetes, ECS, etc.)
- **Push**: Prefect submits runs directly to serverless infra (ECS Push, Cloud Run Push, ACI Push)
- **Managed**: Prefect Cloud handles both submission and execution
- **Workers**: client-side processes that pull scheduled runs from a matching pool and run them
- **Blocks**: typed configuration objects (S3, Slack, Snowflake, GCS, etc.) shared across flows
- **Automations**: event-driven triggers (notify on failure, kick off another deployment, etc.)
### Why Prefect 3
- Native async/await everywhere; first-class concurrency
- Dynamic flows: tasks can be created at runtime, mapped, and conditionally executed
- Hybrid model: code lives where you want, the API server doesn't see your data
- Strong observability via the Prefect UI / Cloud
## Approach
1. Decorate Python functions with `@flow` and `@task`. Keep tasks small and idempotent.
2. Use `.map()` for fan-out and a task runner for parallelism.
3. Configure retries, timeouts, caching, and tags at the decorator level.
4. Author a deployment with `flow.deploy(...)` (image-based) or `flow.serve(...)` (long-running process).
5. Pick a work pool that matches infra: `process` for dev, `docker`/`kubernetes` for production, push pools for serverless.
6. Use blocks for credentials and S3/GCS storage. Trigger downstream deployments via automations.
## Key Patterns
### Flow with retried tasks and mapping
```python
from prefect import flow, task
from prefect.task_runners import ConcurrentTaskRunner
@task(retries=3, retry_delay_seconds=10, timeout_seconds=120)
def fetch_user(user_id: int) -> dict:
import httpx
return httpx.get(f"https://api.example.com/users/{user_id}").json()
@task
def store(user: dict) -> None:
print("storing", user["id"])
@flow(task_runner=ConcurrentTaskRunner())
def sync_users(user_ids: list[int]) -> None:
users = fetch_user.map(user_ids)
store.map(users)
if __name__ == "__main__":
sync_users([1, 2, 3, 4, 5])
```
### Cached task
```python
from prefect import task
from prefect.cache_policies import INPUTS
from datetime import timedelta
@task(cache_policy=INPUTS, cache_expiration=timedelta(hours=1))
def expensive(x: int) -> int:
return x * x
```
### Deploy with `.deploy()` to a Kubernetes work pool
```python
from prefect import flow
@flow
def daily_pipeline():
print("hello from k8s")
if __name__ == "__main__":
daily_pipeline.deploy(
name="daily-pipeline",
work_pool_name="k8s-pool",
image="my-org/pipelines:1.0.0",
cron="0 2 * * *",
job_variables={"memory": "4Gi", "cpu": "2"},
tags=["nightly", "etl"],
)
```
### Serve multiple flows on a long-running process
```python
from prefect import flow, serve
@flow
def hourly_aggregate(): ...
@flow
def nightly_backfill(): ...
if __name__ == "__main__":
serve(
hourly_aggregate.to_deployment(name="hourly", cron="0 * * * *"),
nightly_backfill.to_deployment(name="nightly", cron="30 1 * * *"),
)
```
### Subflow with parameters
```python
from prefect import flow
@flow
def transform(df_path: str): ...
@flow
def orchestrate():
paths = ["s3://raw/a.parquet", "s3://raw/b.parquet"]
for p in paths:
transform(p, return_state=True)
```
### Block usage (S3 credentials)
```python
from prefect_aws import S3Bucket
bucket = S3Bucket.load("warehouse-raw")
bucket.upload_from_path("./output.parquet", "exports/output.parquet")
```
### Worker process (started on the host)
```bash
prefect worker start --pool k8s-pool
```
### Push pool deployment (serverless ECS Fargate)
```python
flow.deploy(
name="serverless-job",
work_pool_name="ecs-push-pool", # push type, no worker needed
image="my-org/job:1.0.0",
cron="0 6 * * *",
job_variables={"cpu": "1024", "memory": "2048"},
)
```
### Automation: trigger deployment B when deployment A succeeds
Configured in the UI, or via:
```python
from prefect.events.schemas.automations import EventTrigger
# Use prefect_cloud / API client to declare automations programmatically
```
## Common Pitfalls
- Using `time.sleep` to wait between tasks instead of letting Prefect manage scheduling.
- Putting non-deterministic work inside `@task` and turning on caching — stale results.
- Returning huge objects between tasks instead of writing to S3 and passing a path.
- Mixing `flow.serve()` (long-running) and `flow.deploy()` (per-run infra) without intent.
- Running a worker pointed at a pool of a different type (`process` worker on a `kubernetes` pool).
- Hardcoding credentials inside flow code instead of using blocks.
- Forgetting `--limit` on a worker — it can pull more concurrent runs than the host can handle.
## When to Use This Mode
- Orchestrating Python ETL/ELT, ML, or data ops jobs across mixed infrastructure
- Replacing brittle cron + bash with retried, observable, parameterizable workflows
- Hybrid environments where some flows run on Kubernetes, some on local agents, some serverless
- Adding event-driven triggers and notifications to existing pipelines
- Standardizing dev → CI → prod deployment of pipelines via code
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!