FAQ
Real questions about Flux — Windows support, the smallest deployment, comparison to other engines, Python version requirements, and more.
Questions that come up before installation, plus a few that come up after. Short answers with links to the page that has the full story.
Does Flux run on Windows?
Yes. Flux is pure Python and targets 3.12+, which supports Windows. The server, workers, and CLI all run natively on Windows. For production, terminate TLS at IIS or a reverse proxy and forward to Flux on the loopback interface — Flux itself has no built-in TLS in 0.56.0.
Can I run Flux without a server, using .run() only?
Yes, for development. workflow.run(input) runs the workflow in-process against SQLite — no server, no worker, no network. It’s the path used by the tests/examples/ suite in the Flux repository. For production, run the server: you get the REST API, scheduling, the MCP server, distributed workers, RBAC, and persistence to PostgreSQL.
Does Flux have a managed cloud offering?
Not in 0.56.0. Flux is self-hosted. The team has not announced a managed service. See Deployment for self-hosting patterns covering Docker, Kubernetes, and the major cloud providers.
How does Flux compare to Temporal, Prefect, or Airflow?
Short version: Flux is async-Python-first, single-binary, and brings agents into the same execution model as workflows. Temporal is the closest in execution semantics but requires a separate cluster and uses SDK shims per language. Prefect is the closest in surface area but treats agents as a separate product. Airflow is DAG-first and operator-heavy. See Versus alternatives for a side-by-side.
What’s the smallest possible Flux deployment?
A single Python process running both flux start server and flux start worker (in separate threads or as &-backgrounded processes), backed by SQLite. No external services, no orchestrator, no LB. Useful for development, evaluations, and small-team production where uptime guarantees are modest. See Local development.
Can workers run on a different host than the server?
Yes — that’s the default production topology. The worker registers over HTTP, then maintains an SSE stream for dispatch. Workers can sit on different hosts, in different regions, behind NAT, anywhere they can reach the server over HTTP(S). The server doesn’t initiate connections to workers; the worker holds the SSE stream open. See Distributed execution.
Which Python versions does Flux support?
Python 3.12 or later. Flux 0.56.0’s pyproject.toml sets python = "^3.12", and CI runs the unit suite on 3.12 through 3.14. The codebase uses PEP 695 generics (3.12+); anything older than 3.12 is not supported and there are no plans to backport.
How do I run multiple Flux servers?
Run N replicas behind a load balancer, backed by PostgreSQL — supported since the 0.36–0.53 line. Replicas coordinate through the database, so there is no leader election to configure: scheduler dispatch and retention run as fleet-wide singletons via PostgreSQL advisory locks, execution dispatch is double-assign-safe (FOR UPDATE SKIP LOCKED), and worker heartbeats persist to the database so every replica shares the same liveness view. The one routing requirement is connection affinity (sticky sessions) for the worker SSE stream; plain round-robin works for everything else. SQLite deployments remain single-server. See High availability.
Where do secrets live?
In Flux’s database, encrypted at rest. Encryption uses PyCryptodome AES with PBKDF2 key derivation; the key comes from [flux.security.encryption] encryption_key (or FLUX_SECURITY__ENCRYPTION__ENCRYPTION_KEY). The encryption key is not defaulted in 0.56.0 — you must set it explicitly, and back it up alongside the database: execution inputs/outputs and event values are HMAC-signed with it, so a restore without the key leaves that data unreadable. Secrets are referenced from tasks via secret_requests=["name", ...] and surfaced as a dict[str, str] inside the task. See Secrets.
Can I add a new LLM provider?
Yes, by modifying the Flux source — there is no plugin API in 0.56.0. Drop a module into flux/tasks/ai/, implement a (factory, formatter) pair conforming to formatter.py::LLMFormatter, and register it. The existing providers (ollama.py, openai.py, anthropic.py, gemini.py) are the templates. A plugin entry-point API is on the roadmap but not in this release. See Choosing a model.
What’s the upgrade path between Flux versions?
Flux versions follow semver. Patch releases are drop-in. Minor releases may add config keys and new public surface but won’t remove the old ones. Major releases (none yet) reserve the right to break. Schema changes are Alembic-managed: migrations ship inside the package and run automatically the first time a server, worker, or inline run opens the database, and databases created by older create_all-based versions are stamped and upgraded in place with data preserved. For explicit control over timing — running migrations once before rolling out multiple replicas — use flux db upgrade|current|history. Back up the database (and your encryption key) before upgrading production. See Upgrades and migrations.
Does Flux do retries automatically?
Tasks retry on failure when you set retry_max_attempts on @task.with_options(...). Default is no automatic retry. The chain is retry → fallback → rollback; each step emits its own event types so you can see in the event log which step ran. See Retries.
How is replay different from retry?
Retry re-runs a failed task. Replay reconstructs the state of a paused or resumed workflow by walking the event log forward — for each completed task, the recorded output is returned without re-executing the task body; for the first incomplete task, the body runs. Retry happens inside a single execution; replay happens across the boundaries of a paused execution. See Replay.
Can I export workflow event logs?
Yes. Events are SQL rows in the execution_events table (model: ExecutionEventModel). Query the database directly, or use flux execution show <id> --format json for one execution at a time. The OpenTelemetry exporter, when enabled, also emits a span per event to your tracing backend. See Observability.
Does Flux support PostgreSQL?
Yes — install the postgresql extra (pip install 'flux-core[postgresql]', which brings in the psycopg v3 driver) and set database_url = "postgresql://user:pass@host/dbname" under [flux] or FLUX_DATABASE_URL. SQLite is the default; PostgreSQL is the recommended production backend because SQLite doesn’t support the concurrent writes a busy server demands (and multi-replica and multi-worker coordination require it). The schema is Alembic-managed — migrations run automatically on first connect. See Database backends.
Can I run agents without an LLM provider installed?
No, but agents are an optional feature. The default install gives you the SDK and the server with no LLM providers. Install the ai extra (poetry install --extras ai) to enable Ollama, OpenAI, Anthropic, and Gemini. If you never use @agent, you can ignore the AI surface entirely. See Installation.
How do I cancel a running workflow?
flux workflow cancel <workflow_name> <execution_id>. The execution transitions to CANCELLING and then to CANCELLED when the worker observes the cancellation. Long-running tasks don’t get interrupted mid-call — Flux signals cancellation between events, so a task currently calling a slow API runs to completion before the cancellation takes effect. See Cancelling executions.
Can I run Flux behind a reverse proxy?
Yes — that’s the recommended production setup. nginx, Caddy, an AWS ALB, or a Kubernetes ingress controller all work. The one constraint is that the proxy must preserve long-lived connections for the worker SSE stream; raise the idle timeout to at least 5× the heartbeat interval (50 seconds for the default). See Reverse proxy and Production deployment.