Prefect is an open-source workflow orchestrator that replaces rigid DAG frameworks with Python-native code, automated retries, and local observability.
Prefect is a workflow orchestration framework that coordinates and monitors data pipelines in Python. Standard functions decorated with flow and task wrappers run as observable workflows without requiring complex directed acyclic graphs in a domain-specific language. A self-hosted server provides scheduling, event triggers, and UI observability while keeping data processing inside private compute infrastructure.
Prefect Cloud manages the control plane as a hosted service, handling API traffic, team workspaces, and dashboard telemetry for a per-seat subscription. Self-hosted Prefect runs that control plane inside your own infrastructure. For developers, the authoring experience is identical: you write standard Python code, apply decorators, configure concurrency limits, and schedule runs via CLI or web UI. Self-hosting avoids recurring fees and keeps all execution metadata, parameters, and logs inside private networks.
The trade-off is operational ownership. Prefect Cloud provides managed Single Sign-On, role-based access control, audit logs, and push work pools that launch container jobs without standing workers. Self-hosting requires DevOps engineers to run the FastAPI server, manage a PostgreSQL database, and supervise worker daemons. Compared to managed Airflow on Astronomer Cloud, Prefect makes local debugging and dynamic branching simpler, but internal teams own server uptime and database maintenance.
What is the difference between Prefect and Prefect Cloud? Prefect is the self-hosted orchestration engine and web interface for private infrastructure, while Prefect Cloud is a hosted service adding managed availability, SSO, RBAC, and audit logs.
Can I use Prefect for commercial applications for free? Yes. Prefect uses an Apache-2.0 license, allowing free commercial deployment and customization without software fees.
How does Prefect differ from Apache Airflow? Prefect uses standard Python function decorators and sub-second dynamic scheduling rather than pre-compiled DAG configuration files, simplifying local testing and parameter handling.
Prefect is an ideal choice for Python teams that want developer-friendly workflow orchestration and complete infrastructure ownership. If your organization requires built-in enterprise role-based access control or a fully managed control plane, Prefect Cloud or an enterprise scheduler is easier to maintain. An Apache-2.0 license permits unrestricted internal deployment and modification, with steady commits into late 2026 showing active project development.
We started this exact setup from scratch in a clean Linux machine on Nov 1, 2026 and checked it through Prefect's own API: every check passed. Recipes are re-checked regularly and removed if they stop working.
mkdir -p prefect && cd prefect
curl -fsSL https://open-source.store/tools/prefect/compose.yml -o compose.ymlcat > .env <<EOF
POSTGRES_PASSWORD=$(openssl rand -hex 12)
PREFECT_UI_API_URL=http://localhost:4200/api
PREFECT_SERVER_API_AUTH_STRING=$(openssl rand -hex 12)
EOFPOSTGRES_PASSWORD — Password of the bundled PostgreSQL database. Generated above; keep it secret.PREFECT_UI_API_URL — Public API URL used by the web UI in the browser; set this to your server's public URL.PREFECT_SERVER_API_AUTH_STRING — Password for HTTP Basic Authentication to the Prefect API and UI (username: admin). Generated above; keep it secret.docker compose up -dservices:
prefect:
image: prefecthq/prefect:3.9.1-python3.12
ports:
- "4200:4200"
depends_on:
postgres:
condition: service_healthy
environment:
PREFECT_SERVER_DATABASE_CONNECTION_URL: postgresql+asyncpg://prefect:${POSTGRES_PASSWORD}@postgres:5432/prefect
PREFECT_SERVER_API_HOST: "0.0.0.0"
PREFECT_SERVER_API_PORT: "4200"
PREFECT_UI_API_URL: ${PREFECT_UI_API_URL}
PREFECT_SERVER_API_AUTH_STRING: "admin:${PREFECT_SERVER_API_AUTH_STRING}"
command: prefect server start
restart: always
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request as u; u.urlopen('http://127.0.0.1:4200/api/health')"]
interval: 10s
timeout: 5s
retries: 5
start_period: 20s
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: prefect
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: prefect
volumes:
- prefect-db-data:/var/lib/postgresql/data
restart: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -U prefect -d prefect"]
interval: 5s
timeout: 5s
retries: 5
volumes:
prefect-db-data:
Lint, codegen, breaking-change checks and dependency management in one Git-native CLI. Open source, no registry lock-in.
Show that Prefect is listed as an open-source alternative. Paste into your README:
Ubuntu 24.04 · Apple container, Docker 29.1.3, Compose 2.40.3+ds1-0ubuntu1~24.04.1. Images pulled in 54 s: prefecthq/prefect:3.9.1-python3.12, postgres:16-alpine.
Based on the upstream setup. Official self-hosted setup with PostgreSQL backend; image pinned to 3.9.1-python3.12, database password moved to .env, basic authentication enabled, and UI API URL made configurable via .env.
prefect-1 | 2026-11-01T08:36:32.184735420Z 08:36:32.183 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:32.184979545Z 08:36:32.184 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:32.185266295Z 08:36:32.185 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:32.189311920Z 08:36:32.189 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:32.190076545Z 08:36:32.189 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:32.190365837Z 08:36:32.190 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:32.191696920Z 08:36:32.191 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:32.237690087Z 08:36:32.237 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:32.238723795Z 08:36:32.237 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:32.238736045Z 08:36:32.238 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:32.241212128Z 08:36:32.240 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:34.195391296Z 08:36:34.194 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:34.207948879Z 08:36:34.207 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:34.278768296Z 08:36:34.278 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:35.623700755Z 08:36:35.622 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:35.624398880Z 08:36:35.623 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.342439547Z 08:36:36.341 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.342725589Z 08:36:36.342 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.343567839Z 08:36:36.342 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.343576255Z 08:36:36.343 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.344033672Z 08:36:36.343 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.344431589Z 08:36:36.344 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.344847339Z 08:36:36.344 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.350671880Z 08:36:36.350 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.358441630Z 08:36:36.357 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.358847922Z 08:36:36.358 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.359253714Z 08:36:36.358 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.360403589Z 08:36:36.359 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.360412214Z 08:36:36.359 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.360477297Z 08:36:36.360 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.365214839Z 08:36:36.364 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.365639755Z 08:36:36.365 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.366491297Z 08:36:36.366 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.366756589Z 08:36:36.366 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.367174339Z 08:36:36.366 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.367578214Z 08:36:36.367 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.368026089Z 08:36:36.367 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.368445297Z 08:36:36.368 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.369671380Z 08:36:36.369 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.370065380Z 08:36:36.369 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.370740964Z 08:36:36.370 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.370844464Z 08:36:36.370 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.372174880Z 08:36:36.371 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.372918672Z 08:36:36.372 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.373879880Z 08:36:36.373 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.374351047Z 08:36:36.374 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.374786005Z 08:36:36.374 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.375624672Z 08:36:36.375 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.376290005Z 08:36:36.375 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.376825464Z 08:36:36.376 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.377428630Z 08:36:36.377 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.379602214Z 08:36:36.377 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.380666630Z 08:36:36.380 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.381204380Z 08:36:36.380 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.383218672Z 08:36:36.382 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.383726922Z 08:36:36.383 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.385229839Z 08:36:36.384 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.386059964Z 08:36:36.385 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.387829922Z 08:36:36.387 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.388495880Z 08:36:36.388 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.389985422Z 08:36:36.389 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.390745464Z 08:36:36.390 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.392044255Z 08:36:36.391 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.392850047Z 08:36:36.392 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.394040422Z 08:36:36.393 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.394572047Z 08:36:36.394 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.395802839Z 08:36:36.395 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.396369672Z 08:36:36.396 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.397479422Z 08:36:36.397 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.398010422Z 08:36:36.397 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.400240505Z 08:36:36.399 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.401027172Z 08:36:36.400 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.402526464Z 08:36:36.401 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.403304172Z 08:36:36.402 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.404748922Z 08:36:36.404 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.405771297Z 08:36:36.405 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.406930089Z 08:36:36.406 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:36.407280589Z 08:36:36.406 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.214991131Z 08:36:37.214 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.216665881Z 08:36:37.215 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.219893631Z 08:36:37.218 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.220316131Z 08:36:37.219 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.221641089Z 08:36:37.221 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.222738922Z 08:36:37.221 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.224862506Z 08:36:37.224 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.226101672Z 08:36:37.225 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.301958006Z 08:36:37.299 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.302010672Z 08:36:37.301 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.307907922Z 08:36:37.304 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.307937131Z 08:36:37.305 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.307941047Z 08:36:37.306 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.307943339Z 08:36:37.306 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.308255589Z 08:36:37.307 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.310065464Z 08:36:37.307 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.313632339Z 08:36:37.311 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.314202589Z 08:36:37.313 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.319729172Z 08:36:37.318 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.322129172Z 08:36:37.319 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.325547881Z 08:36:37.324 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:37.326095172Z 08:36:37.324 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:38.157169964Z 08:36:38.156 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:38.157786631Z 08:36:38.157 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:38.158758964Z 08:36:38.158 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:38.159235298Z 08:36:38.158 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:38.329524798Z 08:36:38.328 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:38.330346339Z 08:36:38.329 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:39.154324965Z 08:36:39.153 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:39.155716548Z 08:36:39.154 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:39.157535715Z 08:36:39.156 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:39.158351590Z 08:36:39.157 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:39.159710382Z 08:36:39.159 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:39.160710632Z 08:36:39.160 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:39.161495382Z 08:36:39.161 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:39.161920715Z 08:36:39.161 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:39.163275048Z 08:36:39.162 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:39.163775923Z 08:36:39.163 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:39.230945048Z 08:36:39.230 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:39.231591840Z 08:36:39.231 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:43.318885342Z 08:36:43.317 | WARNING | uvicorn.error - Invalid HTTP request received. prefect-1 | 2026-11-01T08:36:43.318931092Z 08:36:43.318 | WARNING | uvicorn.error - Invalid HTTP request received.