Skip to content
Latchkey LogoLatchkey home

GitHub Actions vs Argo Workflows: which one runs what

GitHub Actions vs Argo Workflows is usually a false choice, because the two are not sold the same unit of work: Actions runs a workflow file in response to a git event, and Argo Workflows reconciles a Kubernetes custom resource that models a DAG of containers. The place they genuinely collide is fan-out, where Actions caps a job matrix at 256 jobs per run and Argo is bounded by the cluster.

One Actions job as a single runner with five steps, next to five Argo pods of three containers
The same five steps on each engine. Actions shares one runner and one filesystem; Argo generates a pod per step, historically with an init and a wait container around your own image.

Argo Workflows is a container-native workflow engine implemented as a Kubernetes CRD, and a graduated project in the Cloud Native Computing Foundation. Its own documentation lists its use cases in this order: machine learning pipelines, data and batch processing, infrastructure automation, and CI/CD. CI/CD is fourth on that list for a reason.

GitHub Actions is triggered by repository events, runs on machines somebody else keeps warm, and reports back into the pull request. Argo has no git trigger of its own; event-driven triggering is a separate project, Argo Events, that you also deploy.

The comparison below is drawn from the argoproj/argo-workflows repository and from GitHub's published limits, read on 21 September 2026 against Argo Workflows v4.1.4. Where a number depends on your cluster, the cell says so.

GitHub Actions against Argo Workflows, by what each one actually is (read 21 September 2026)

GitHub ActionsArgo Workflows
The unit you writeA workflow file in .github/workflows, up to 500 KB, discovered automatically from the repositoryA Workflow custom resource applied to a cluster, with steps or a DAG of tasks
What triggers itPush, pull request, schedule, manual dispatch and the rest of the repository event setThe API, the argo CLI, a schedule, or sensors from the separate Argo Events project
What runs a stepAll steps of a job share one runner and one filesystemEvery step and every DAG task becomes its own Pod, historically three containers: main, init and wait
Fan-out ceilingA job matrix generates at most 256 jobs per workflow run, on hosted and self-hosted runners alikeYour cluster. The controller processes one Workflow at a time, so the ceiling moves from the API to the reconciler
What you pay per minute$0.006 at 2 vCPU on Linux, or $0.0025 on a managed runner at the same sizeNothing to Argo. Your cluster bills for the pods and the nodes under them
Free tier2,000 minutes a month on Free, 3,000 on Team, 50,000 on Enterprise Cloud, and free and unlimited on public repositoriesApache 2.0 software, no allowance, because there is no meter
Where it runsGitHub's fleet, a vendor's fleet, or your own self-hosted runnersA Kubernetes cluster you operate, with the controller and server in their own namespace
Time limits6 hours per job on hosted runners, 5 days self-hosted, 35 days per workflow runWhatever you configure. The quick-start instructions say in as many words that they are not suitable for production
Self-healing or retriesNone built in on GitHub-hosted runners; transient failures diagnosed and retried inside the run on LatchkeyRetry strategies you declare per template, which is real retry logic and the most convincing thing on this row
Setup change requiredCommit a file. On a managed runner, an app install and a runs-on labelA Kubernetes cluster, kubectl, the quick-start or production manifests, and the argo CLI

What a step costs on each side

This is the difference that surprises people who try to run CI on Argo. In GitHub Actions a job is one machine: checkout, install, build and test all see the same working directory, and passing data between steps costs nothing. In Argo, each step and each DAG task causes a Pod to be generated. Historically each of those pods carries three containers: main runs your image, an init container fetches artifacts and parameters, and a wait container handles clean-up and saves parameters and artifacts back out.

That design is exactly right for the work Argo was built for, where a step is a training run or a batch transform and a pod of overhead is rounding error. It is exactly wrong for a five-step CI job, where you would be paying pod scheduling and artifact round-trips to move a node_modules directory between steps that could have shared a disk.

The project is moving on this. An opt-in beta layout, enabled with initlessPod.enabled: true, drops to two containers with zero init containers by delivering the argoexec binary into main through a Kubernetes image volume, with a supervisor container taking over both the pre-main and post-main work. It is worth knowing about, and it is still opt-in.

The fan-out ceiling, which is the real reason to compare them

GitHub publishes a hard number here and most teams meet it by accident: a job matrix can generate a maximum of 256 jobs per workflow run, and that limit applies to GitHub-hosted and self-hosted runners alike. If your test suite shards into 300 pieces, or your matrix multiplies four dimensions together, Actions will not start the run.

Argo has no equivalent published cap, because the limit is the cluster you gave it. What it has instead is a different bottleneck worth knowing: the workflow controller only ever processes a single Workflow at a time, reconciling from a queue of worker goroutines. That does not cap parallelism inside one workflow, but it does mean the controller is the thing to watch when many workflows are in flight, in the same way the 256 is the thing to watch in Actions.

So the honest rule is about shape rather than about which is better. Wide, uniform, long-running fan-out belongs on Argo. Everything triggered by a pull request belongs where the pull request is.

Speed

Not benchmarked yet, and this is one of the pages where a benchmark would be dishonest even if we ran one. The two systems do not execute the same unit of work: a like-for-like test would have to invent a workload that suits neither, and the result would measure our cluster against GitHub's fleet rather than the engines.

The mechanical statement that does hold: a GitHub Actions job pays its startup once and then runs every step on a warm machine, while an Argo workflow pays pod scheduling per step. For a DAG of ten long tasks that is invisible. For a chain of ten short ones it is most of the wall clock.

Cost: the meter and the cluster

Ten thousand Linux minutes a month is $60 at GitHub's $0.006 list rate for a 2 vCPU runner, or $42 on a Team plan once the 3,000 included minutes are applied, and $25 at $0.0025 on a managed runner at the same size. Those are published rates and one multiplication.

Argo bills nothing and costs whatever its pods cost. That is genuinely cheaper for sustained, high-utilization batch work, where a node pool runs hot all day and the alternative would be metered minutes at a vendor rate. It is genuinely more expensive for bursty CI, where you are keeping capacity warm for pull requests that arrive in clumps. Nobody should port a CI pipeline to Argo to save money without first measuring what fraction of the day their cluster would be idle.

Why there is no recorded run on this page

The reproduction harness on this site records a named workload on a Latchkey runner. There is no workload that both systems run natively: a DAG written as a Workflow resource has no meaning to the Actions service, and a workflow file has none to the Argo controller. Any run we published would be a translation we wrote, and the translation, not the engine, would be what the numbers measured. The facts this page rests on are a published limit and a repository, both linked below.

Running both, which is what most teams do

  • Keep pull request checks, builds and releases on GitHub Actions, where the event, the status check and the merge gate already live.
  • Put the wide batch work on Argo: training runs, nightly ETL, anything that fans out past the 256-job matrix ceiling or runs long enough that pod overhead disappears.
  • Let Actions start the Argo workflow rather than reimplementing either inside the other. A job that submits a Workflow and waits is a small amount of YAML and keeps each engine doing what it is shaped for.
  • If the only reason Argo is on the table is that Actions minutes are expensive, price a managed runner first. It is a label change, not a platform migration, and it does not add a controller to operate.

The verdict

These two are complements that get compared because both are configured in YAML. Argo Workflows is the better engine for container DAGs on Kubernetes, it has real per-template retry semantics, and its fan-out is limited by hardware rather than by a published cap. GitHub Actions is the better engine for anything a commit should trigger, because that is the event it is built on and because the result belongs in the pull request. Choosing Argo for CI means operating a controller, a server and a cluster so that a test suite can run, and paying a pod per step for the privilege. If the cost of Actions minutes is what pushed you to look, the cheaper fix is a different runner rather than a different engine.

Frequently asked questions

Can Argo Workflows replace GitHub Actions for CI?
It can run the containers, but it does not replace the part most teams actually use. Argo has no git trigger of its own, so you would deploy Argo Events as well, and the result still has to be reported back into the pull request by something. Its own documentation ranks CI/CD fourth in its use-case list, behind machine learning pipelines, data processing and infrastructure automation.
What is the maximum matrix size in GitHub Actions?
256 jobs per workflow run. GitHub states that a job matrix can generate a maximum of 256 jobs per workflow run and that the limit applies to both GitHub-hosted and self-hosted runners, so adding your own runners does not raise it. Shard into fewer, larger jobs, or split the matrix across workflows.
Why is each Argo step its own pod?
Because the unit Argo schedules is a container, not a machine. Each step and each DAG task generates a Pod, historically with three containers: main for your image, an init container that fetches artifacts and parameters, and a wait container that saves outputs and cleans up. An opt-in beta layout reduces that to two containers with no init container.
Do I need Kubernetes to use Argo Workflows?
Yes. Argo Workflows is implemented as a Kubernetes custom resource definition, and the install instructions start by requiring a cluster and a configured kubectl. Local clusters such as kind or k3s are fine for trying it; the project warns that its quick-start instructions are not suitable for production.

Related guides

References

Changing the runner is one line. Changing the engine is a quarter. Latchkey is $0.0025/min at 2 vCPU. Start free → 30-day trial · No credit card