---
title: "GitHub Actions Too Slow? Find the Cause, Then Fix It"
description: "Diagnose slow GitHub Actions by separating queue wait, runner hardware, and workflow waste, then apply the fix that matches the bottleneck."
url: https://starsling.dev/github-actions-too-slow
canonicalUrl: https://starsling.dev/github-actions-too-slow
dateModified: 2026-07-14
---

# GitHub Actions too slow?

When a GHA run is slow, the hard part is knowing whether the job waited for capacity, ran on underpowered hardware, or repeated work the workflow could skip. This guide starts with the run timeline, then routes each cause to the smallest useful fix.

**Topics covered:** This guide covers how to tell whether a slow run is waiting in a queue, starved by runner hardware, or wasting work in the workflow, and which fix to try first.

## Canonical answer

Slow GitHub Actions has three common causes: jobs wait in a queue before a runner starts, the runner hardware cannot finish the work quickly, or the workflow repeats unnecessary work. Compare created_at to started_at, rerun the same job on stronger Ubuntu hardware, and inspect checkout, install, build, test, and trigger timing before choosing a fix.

## Key caveats

- The right fix depends on your own run timeline; a faster runner does not fix a deploy approval, an external API wait, or a fixed sleep.
- StarSling runners are Ubuntu/Linux only; macOS and Windows jobs stay on GitHub-hosted runners.
- StarSling keeps GitHub Actions syntax and branch protections. It is not a replacement CI platform.
- For new accounts, AI-powered optimization PRs are only available to customers on paid plans and are not enabled by default.

## TL;DR

- Start with timestamps. Queue wait is the gap between the run or job being created and the job actually starting.
- If queue wait dominates, fix capacity and concurrency first. If execution dominates, test whether runner hardware or workflow waste is the long pole.
- Already know the runner is the limit? Go straight to [Fast GitHub Actions](/fast-github-actions). If not, diagnose first so you do not optimize the wrong stage.

## Diagnose the cause

Use the run timeline as the routing table. The same slow PR can have more than one cause, but one usually dominates the developer wait.

| Cause | How to check | Best next fix |
| --- | --- | --- |
| Queue wait before a runner starts | Compare `started_at` with `created_at` for the job. A large gap before the first step means the workflow is waiting for capacity or serialized by concurrency. | Read [cut GitHub Actions queue time](/best-practices/github-actions/cut-queue-time), scope concurrency per ref, cancel superseded PR runs, and use runner capacity that can absorb bursts. |
| Runner hardware is the limit | The job starts promptly, but CPU-heavy build, test, compression, or toolchain steps still take most of the wall-clock time. Rerun the same job on stronger Ubuntu hardware and compare the same step timings. | Use a faster Linux runner label and keep the workflow unchanged. The migration is a `runs-on` change; see [Fast GitHub Actions](/fast-github-actions). |
| Workflow waste repeats work | Checkout, dependency install, Docker build, monorepo build, or test steps dominate even when inputs barely changed. Look for missing caches, full-history checkout, one long test job, broad triggers, and obsolete steps. | Apply the matching best practice: [cache dependencies](/best-practices/github-actions/cache-dependencies), [shallow checkout](/best-practices/github-actions/shallow-checkout), [build only affected projects](/best-practices/github-actions/build-only-affected), [shard tests](/best-practices/github-actions/shard-tests), or [path filters](/best-practices/github-actions/path-filter-workflows). |

## If hardware is the cause, the first test is one line

Keep GitHub Actions syntax and compare the same job on a [supported StarSling Ubuntu runner](https://docs.starsling.dev/runners/instance-types). Move only Ubuntu/Linux jobs; leave macOS and Windows on GitHub-hosted runners.

### Before

```yaml
runs-on: ubuntu-latest
```

### After

```yaml
runs-on: starsling-ubuntu-24.04
```

- Do not change steps during the first measurement, or you will not know what caused the delta.
- Compare the same job, on a similar commit, with the same cache warmth if possible.
- If the execution time barely moves, the bottleneck is probably workflow waste, networking, or an approval wait.

## Workflow waste checks

When execution time dominates but hardware is not the whole answer, inspect the expensive stages in this order.

| Smell | Evidence in the run | Guide |
| --- | --- | --- |
| Dependency install repeats from scratch | Package-manager install time is high on most PR runs, and setup actions show no cache hit tied to a lockfile. | [Cache dependencies](/best-practices/github-actions/cache-dependencies) |
| Checkout pulls too much history | `actions/checkout` uses `fetch-depth: 0` on jobs that only need the current tree. | [Use shallow checkout](/best-practices/github-actions/shallow-checkout) |
| One test job is the long pole | The whole PR waits on one suite while other jobs finish early. | [Shard tests](/best-practices/github-actions/shard-tests) |
| Docs-only changes run expensive suites | Workflow triggers do not distinguish source changes from unrelated files. | [Path-filter guide for source-scoped workflows](/best-practices/github-actions/path-filter-workflows) |
| Monorepo builds everything | A small package change starts builds and tests for projects the diff cannot affect. | [Build only affected projects](/best-practices/github-actions/build-only-affected) |

## Paste this into your agent

This prompt asks for diagnosis before edits. That keeps the PR focused on the bottleneck instead of collecting unrelated CI tweaks.

Inspect the most recent slow GitHub Actions run and separate the wait before each job starts from the time the job spends executing steps. Report queue wait as started_at minus created_at, then group the execution time by checkout, dependency install, build, tests, Docker, deploy, and fixed sleeps. Decide whether the dominant cause is queue wait, runner hardware, or workflow waste. For each cause, propose the smallest safe fix, link it to the exact workflow lines, and say what measurement would prove the fix worked. Do not rewrite CI syntax or weaken required checks. Open one focused PR only if the evidence points to a clear fix.

## Public examples to inspect

The customer proof above is ratio-only and comes from published case studies. For public repository examples, inspect the diffs rather than the PR titles: these changes keep GitHub Actions and swap supported Ubuntu jobs to StarSling runner labels.

Use these as migration-shape examples, not as a promise that every workflow gets the same multiplier. Your timeline still decides whether queue wait, hardware, or workflow waste is the first fix.

- [better-auth#7933 runner-label migration](https://github.com/better-auth/better-auth/pull/7933)
- [mastra#13466 runner-label migration](https://github.com/mastra-ai/mastra/pull/13466)
- [mastra#16015 runner-label migration](https://github.com/mastra-ai/mastra/pull/16015)

## When StarSling helps most

StarSling tends to help most when the diagnosis points to runner capacity, runner speed, or CI workflow waste in supported Ubuntu jobs.

- Your jobs already run on `ubuntu-latest` or `ubuntu-24.04`.
- Queue wait or CPU-bound execution is visible in the run timeline.
- Install, checkout, test, or trigger waste can be turned into reviewable optimization PRs.
- You want to keep GitHub Actions workflows, branch protections, checks, and review flow.

If the run is slow because of deploy approvals, third-party API waits, fixed sleeps, or macOS and Windows jobs, solve those directly; a faster Linux runner is not the lever.

- [Fast GitHub Actions](https://starsling.dev/fast-github-actions)
- [GitHub Actions runner alternatives](https://starsling.dev/github-actions-runners-alternatives)
- [GitHub Actions CI best-practices catalog](https://starsling.dev/best-practices/github-actions)

## FAQ

### Why is my GitHub Actions workflow queued for so long?

Long queue time usually means the job is waiting for available runner capacity or is serialized by a concurrency group. Measure the gap between created_at and started_at, then check whether superseded PR runs are still occupying capacity and whether concurrency is scoped too broadly.

### Why is GitHub Actions so slow even after the job starts?

Once the job starts, slow execution usually comes from runner hardware, dependency installs, full checkout history, Docker builds, one long test job, monorepo work that runs too broadly, or fixed waits inside tests and deploy setup.

### Do bigger or faster runners actually help slow GitHub Actions?

They help when the job is CPU-bound, memory-bound, or queue-bound on runner capacity. They do not help deploy approvals, external API waits, fixed sleeps, or workflow work that should have been cached, skipped, or parallelized.

### How do I tell whether the runner or the workflow is the bottleneck?

Rerun the same job on stronger Ubuntu hardware without changing steps. If the expensive steps shrink, runner hardware mattered. If they do not, inspect workflow waste such as missing caches, full checkout history, unsharded tests, broad triggers, or fixed sleeps.

### What should I fix first if GitHub Actions is taking too long?

Fix the largest measured wait first. Queue wait points to concurrency and capacity. CPU-heavy execution points to runner hardware. Repeated setup or irrelevant jobs point to caching, checkout, affected builds, sharding, and path filters.

### Is StarSling a replacement for GitHub Actions?

No. StarSling keeps GitHub Actions workflows and changes supported Ubuntu/Linux runner labels. The workflow syntax, checks, branch protections, and PR review process stay in GitHub Actions.

## Related resources

- [Fast GitHub Actions](https://starsling.dev/fast-github-actions)
- [Cut GitHub Actions queue time](https://starsling.dev/best-practices/github-actions/cut-queue-time)
- [Cache dependencies](https://starsling.dev/best-practices/github-actions/cache-dependencies)
- [Shallow checkout](https://starsling.dev/best-practices/github-actions/shallow-checkout)
- [Shard tests](https://starsling.dev/best-practices/github-actions/shard-tests)
- [Build only affected projects](https://starsling.dev/best-practices/github-actions/build-only-affected)
- [Path-filter workflows](https://starsling.dev/best-practices/github-actions/path-filter-workflows)
- [GitHub Actions runner alternatives](https://starsling.dev/github-actions-runners-alternatives)
- [How Partcl cut CI queue time 16x](https://starsling.dev/customers/partcl)
- [How Mastra got 6x faster GitHub Actions tests](https://starsling.dev/customers/mastra)
- [How Better Auth got 2x faster E2E tests](https://starsling.dev/customers/better-auth)

## CTA

- [Find the slow part, then run it faster](https://github.com/apps/starslingdev)
- [Fast GitHub Actions](https://starsling.dev/fast-github-actions)
