Compose tasks with fanout, parallelism, error handling, traces, files, and DataFrames.

Build tasks

This section covers the essential programming patterns and techniques for developing robust Flyte workflows. Once you understand the basics of task configuration, these guides will help you build sophisticated, production-ready data pipelines and machine learning workflows.

What you’ll learn

The task programming section covers key patterns for building effective Flyte workflows:

Data handling and types

  • Files and directories: Work with large datasets using Flyte’s efficient file and directory types that automatically handle data upload, storage, and transfer between tasks.
    • Volumes: Mount a persistent file system and use it from within your task like an ordinary local directory.
  • DataFrames: Pass DataFrames between tasks without downloading data into memory, with support for Pandas, Polars, PyArrow, Dask, and other DataFrame backends.
  • Data classes and structures: Use Python data classes and Pydantic models as task inputs and outputs to create well-structured, type-safe workflows.
  • Custom context: Use custom context to pass metadata through your task execution hierarchy without adding parameters to every task.

Execution patterns

  • Fanout: Scale your workflows by running many tasks in parallel, perfect for processing large datasets or running hyperparameter sweeps.
  • Mapping over inputs: Apply the same task to every item of a list with flyte.map: in-order results, error handling, concurrency limits, and partials.
  • Consuming a message queue: Pull messages from an external queue such as AWS SQS and fan out processing across a pool of reusable containers.
  • Controlling parallel execution: Limit concurrent task executions using semaphores or flyte.map concurrency for rate-limited APIs, GPU quotas, and resource-constrained workflows.
  • Streaming map-reduce: Process fanout results as they complete with asyncio.as_completed, reducing in batches incrementally instead of waiting for every task to finish.
  • Task dependencies and ordering: Replicate DAG-like behavior (sequencing, fan-out, fan-in, and fine-grained dependency-driven scheduling) using asyncio in Flyte 2’s implicit dependency model.
  • Structured concurrency with anyio: Use anyio task groups as a top-level structured-concurrency alternative to raw asyncio, with automatic sibling cancellation when one task fails.
  • External conditions: Pause a task until an external signal arrives: a human approval, a callback from an external service, or a value supplied at runtime.
  • Grouping actions: Organize related task executions into logical groups for better visualization and management in the UI.
  • Container tasks: Run arbitrary containers in any language without the Flyte SDK installed, using Flyte’s copilot sidecar for data flow.
  • Remote tasks: Use previously deployed tasks without importing their code or dependencies, enabling team collaboration and task reuse.
  • Pod templates: Extend tasks with Kubernetes pod templates to add sidecars, volume mounts, and advanced Kubernetes configurations.
  • Abort and cancel actions: Stop in-progress actions automatically, programmatically, or manually via the CLI and UI.
  • Other features: Advanced patterns like task forwarding and other specialized task execution techniques.
  • Higher-order functions: Write reusable functions that take tasks as arguments — fallback, memory-scaling retry, circuit breaker, and batch map-reduce wrappers built on Flyte’s dynamic execution.

Development and debugging

  • Notebooks: Write and iterate on workflows directly in Jupyter notebooks for interactive development and experimentation.
  • Unit testing: Test your Flyte tasks using direct invocation for business logic or flyte.run() for Flyte-specific features.
  • Links: Add clickable URLs to tasks in the Flyte UI, connecting them to external tools like experiment trackers and monitoring dashboards.
  • Reports: Generate custom HTML reports during task execution to display progress, results, and visualizations in the UI.
  • Traces: Add fine-grained observability to helper functions within your tasks for better debugging and resumption capabilities.
  • Intra-task checkpoints: Save in-progress state within a task (such as a training loop) so retries resume from the last checkpoint instead of starting over.
  • Error handling: Implement robust error recovery strategies, including automatic resource scaling and graceful failure handling.

When to use these patterns

These programming patterns become essential as your workflows grow in complexity:

  • Use fanout when you need to process multiple items concurrently or run parameter sweeps.
  • Use mapping over inputs to apply the same task to every item of a list, and controlling parallel execution when you need to limit how many run at the same time.
  • Apply streaming map-reduce when map tasks have uneven durations or you want to reduce results in batches as they complete, rather than waiting for the entire fanout to finish.
  • Implement error handling for production workflows that need to recover from infrastructure failures.
  • Apply grouping to organize complex workflows with many task executions.
  • Use files and directories when working with large datasets that don’t fit in memory.
  • Use DataFrames to efficiently pass tabular data between tasks across different processing engines.
  • Choose container tasks when you need to run code in non-Python languages, use legacy containers, or execute AI-generated code in sandboxes.
  • Use remote tasks to reuse tasks deployed by other teams without managing their dependencies.
  • Apply pod templates when you need advanced Kubernetes features like sidecars or specialized storage configurations.
  • Use traces to debug non-deterministic operations like API calls or ML inference.
  • Use intra-task checkpoints to make long-running training loops resumable across retries, preemptions, and interruptions.
  • Use links to connect tasks to external tools like Weights & Biases, Grafana, or custom dashboards directly from the Flyte UI.
  • Create reports to monitor long-running workflows and share results with stakeholders.
  • Use custom context when you need lightweight, cross-cutting metadata to flow through your task hierarchy without becoming part of the task’s logical inputs.
  • Write unit tests to validate your task logic and ensure type transformations work correctly before deployment.
  • Use abort and cancel to stop unnecessary actions when conditions change, such as early convergence in HPO or manual intervention.
  • Use external conditions to insert approval gates or data collection checkpoints into automated workflows.
  • Apply higher-order functions to factor recurring orchestration logic — retry-on-OOM, fallback, circuit breaking, batching — into reusable wrappers that work with any task.

Each guide includes practical examples and best practices to help you implement these patterns effectively in your own workflows.

Files and directoriesPass files and directories between tasks with flyte.io.File and flyte.io.Dir.VolumesA durable, versioned file system that tasks mount and read and write like a local directory, with cheap copy-on-write forks.Data classes and structuresPass dataclasses and Pydantic models between tasks as materialized values.DataFramesPass DataFrames between tasks by reference instead of materializing them.Custom typesTeach Flyte to serialize a type its type system does not already handle.Custom contextPass configuration through a task hierarchy without threading it through every signature.Abort and cancel actionsStop actions that are no longer needed while a run is still going.Raw Container TasksRun any container image as a task, with no Flyte SDK installed inside it.LinksAttach clickable URLs to a task so the UI can reach external tools.ReportsDisplay and update custom output in the UI while a task runs.NotebooksWrite and run Flyte workloads from inside a Jupyter notebook.Remote tasksCall an already-deployed task without importing its code or dependencies.Error handlingCatch and recover from task failures, including out-of-memory errors and timeouts.TracesMake a called function observable and resumable with the flyte.trace decorator.Intra-task checkpointsSave progress inside a long-running task so a retry does not start over.Grouping actionsCluster related actions together so a large run stays readable in the UI.FanoutRun many tasks in parallel, and what changes at large scale.Mapping over inputsApply one task across every item of an iterable, in parallel.Consuming a message queueBuild a long-running task that pulls messages from an external queue such as SQS.Controlling parallel executionCap how many fanned-out tasks run at once, for rate limits and quotas.Streaming map-reduceProcess fanned-out results as they finish instead of waiting for all of them.Structured concurrency with anyioUse anyio or trio instead of asyncio, since the graph is built from what you await.Task dependencies and orderingHow ordering comes from ordinary Python data flow rather than an explicit DAG.External conditionsPause a task until an external signal arrives, such as a human approval or a callback.Unit Testing TasksTest task logic locally, with and without a running backend.Higher-order functionsPass tasks to other tasks and return them, since tasks are ordinary Python.Other featuresAdvanced patterns that do not fit the other pages in this section.