DEV Community

Pete Miloravac
Pete Miloravac

Posted on • Originally published at semaphore.io on

Best CI/CD Tools in 2026: Performance and Cost Compared

Choosing a CI/CD tool in 2026 isn’t just a technical decision — it’s a cost and productivity decision. Slow pipelines mean slower shipping, and opaque pricing means budget surprises at the end of the month.

We benchmarked five of the most widely used CI/CD platforms against the same workload: a real Ruby on Rails application (Redmine), with identical OS, runtime version, and database backend across all providers. No cherry-picked runs, no parallelism tricks — just a realistic, repeatable pipeline measured 10 times per provider after cache warm-up.

Here’s what we found.

How We Ran the Benchmark

  • Test application: Redmine — a mature, production-grade Ruby on Rails app used by thousands of teams.
  • Workload per run: Repository checkout → cache restoration → dependency installation → PostgreSQL database setup → full test suite execution.
  • Machine specs: 2 vCPU instances across all providers (the closest standardized tier available on each platform). Ruby 4.0, PostgreSQL, Linux.
  • Measurement: 10 consecutive runs per provider, post cache warm-up, single-job execution (no parallelism). No outliers removed.

This methodology mirrors what most small-to-medium engineering teams actually run day-to-day.

At a Glance: Performance and Cost Rankings

.semaphore-benchmark-embed {
--font-down-1: 0.889rem;
--font-down-2: 0.79rem;
--font-down-3: 0.702rem;

--color-cream: #F7F3EC;
--color-yellow: #FFD517;
--color-orange: #FFAF17;
--color-purple: #A74DC3;
--color-blue: #2865DE;
--color-ink: #0D1421;
--color-green: #16A34A;

box-sizing: border-box;
color: var(--color-ink);
container-type: inline-size;
font-family: inherit;
width: 100%;
Enter fullscreen mode Exit fullscreen mode

}

.semaphore-benchmark-embed *,
.semaphore-benchmark-embed *::before,
.semaphore-benchmark-embed *::after {
box-sizing: inherit;
}

.semaphore-benchmark-embed .chart-card {
background: #fff;
border-color: #c8cbd0;
border-style: solid;
border-width: 1px;
border-radius: 20px;
min-width: 0;
padding: 2rem;
}

.semaphore-benchmark-embed .chart-title {
font-size: var(--font-down-1);
font-weight: 800;
letter-spacing: 0;
margin: 0 0 1.75rem;
text-transform: uppercase;
}

.semaphore-benchmark-embed .benchmark-table-wrap {
overflow-x: auto;
width: 100%;
}

.semaphore-benchmark-embed .benchmark-table {
border-collapse: separate;
border-spacing: 0;
font-size: var(--font-down-1);
min-width: 0;
table-layout: fixed;
width: 100%;
}

.semaphore-benchmark-embed th:nth-child(1),
.semaphore-benchmark-embed td:nth-child(1) {
width: 4.25rem;
}

.semaphore-benchmark-embed th:nth-child(2),
.semaphore-benchmark-embed td:nth-child(2) {
width: 26%;
}

.semaphore-benchmark-embed th:nth-child(3),
.semaphore-benchmark-embed td:nth-child(3),
.semaphore-benchmark-embed th:nth-child(4),
.semaphore-benchmark-embed td:nth-child(4) {
width: 18%;
}

.semaphore-benchmark-embed th {
background: var(--color-cream);
color: var(--color-ink);
font-size: var(--font-down-2);
font-weight: 800;
letter-spacing: 0;
padding: 0.875rem 1rem;
text-align: left;
text-transform: uppercase;
overflow-wrap: anywhere;
}

.semaphore-benchmark-embed th:first-child {
border-top-left-radius: 14px;
}

.semaphore-benchmark-embed th:last-child {
border-top-right-radius: 14px;
}

.semaphore-benchmark-embed td {
border-bottom: 1px solid #e5e7eb;
font-weight: 700;
padding: 1rem;
vertical-align: middle;
overflow-wrap: anywhere;
}

.semaphore-benchmark-embed tbody tr:last-child td {
border-bottom: 0;
}

.semaphore-benchmark-embed .rank-cell {
color: rgba(13, 20, 33, 0.66);
font-weight: 800;
width: 4rem;
}

.semaphore-benchmark-embed .tool-cell {
align-items: center;
display: flex;
gap: 0.5rem;
min-width: 0;
flex-wrap: wrap;
}

.semaphore-benchmark-embed .dot {
border-radius: 50%;
box-shadow: 0 0 0 0.25rem rgba(13, 20, 33, 0.05);
flex: 0 0 0.625rem;
height: 0.625rem;
width: 0.625rem;
}

.semaphore-benchmark-embed .color-semaphore {
background: var(--color-blue);
}

.semaphore-benchmark-embed .color-github {
background: var(--color-yellow);
}

.semaphore-benchmark-embed .color-buildkite {
background: var(--color-orange);
}

.semaphore-benchmark-embed .color-gitlab {
background: var(--color-purple);
}

.semaphore-benchmark-embed .color-circleci {
background: var(--color-ink);
}

.semaphore-benchmark-embed .badge-best {
background: var(--color-green);
border-radius: 999px;
box-shadow: 0 0.375rem 0.875rem rgba(22, 163, 74, 0.24);
color: #fff;
display: inline-block;
font-size: var(--font-down-3);
font-weight: 800;
letter-spacing: 0;
line-height: 1;
margin-left: 0.5rem;
padding: 0.3125rem 0.625rem;
text-transform: uppercase;
vertical-align: middle;
white-space: nowrap;
}

@container (max-width: 57.5rem) {
.semaphore-benchmark-embed .chart-card {
padding: 1.5rem;
}

.semaphore-benchmark-embed th,
.semaphore-benchmark-embed td {
  padding: 0.75rem;
}
Enter fullscreen mode Exit fullscreen mode

}

@container (max-width: 42rem) {
.semaphore-benchmark-embed .chart-card {
padding: 1.25rem;
}

.semaphore-benchmark-embed .benchmark-table-wrap {
  overflow-x: visible;
}

.semaphore-benchmark-embed .benchmark-table,
.semaphore-benchmark-embed thead,
.semaphore-benchmark-embed tbody,
.semaphore-benchmark-embed tr,
.semaphore-benchmark-embed th,
.semaphore-benchmark-embed td {
  display: block;
  width: 100%;
}

.semaphore-benchmark-embed thead {
  clip: rect(0 0 0 0);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

.semaphore-benchmark-embed tbody {
  display: grid;
  gap: 0.625rem;
}

.semaphore-benchmark-embed tr {
  border: 1px solid #e5e7eb;
  border-radius: 14px;
  display: grid;
  gap: 0.5rem 0.625rem;
  grid-template-columns: 2rem repeat(3, minmax(0, 1fr));
  padding: 0.625rem;
}

.semaphore-benchmark-embed td {
  align-items: start;
  border-bottom: 0;
  display: block;
  min-width: 0;
  padding: 0;
  width: auto;
}

.semaphore-benchmark-embed td:nth-child(1),
.semaphore-benchmark-embed td:nth-child(2),
.semaphore-benchmark-embed td:nth-child(3),
.semaphore-benchmark-embed td:nth-child(4),
.semaphore-benchmark-embed td:nth-child(5) {
  width: auto;
}

.semaphore-benchmark-embed td::before {
  color: rgba(13, 20, 33, 0.62);
  content: attr(data-label);
  display: block;
  font-size: var(--font-down-2);
  font-weight: 800;
  margin-bottom: 0.1875rem;
  text-transform: uppercase;
}

.semaphore-benchmark-embed td.rank-cell {
  align-self: center;
  background: var(--color-cream);
  border-radius: 999px;
  display: grid;
  font-size: var(--font-down-1);
  height: 2rem;
  place-items: center;
  width: 2rem;
}

.semaphore-benchmark-embed .rank-cell::before,
.semaphore-benchmark-embed td:nth-child(2)::before {
  content: none;
}

.semaphore-benchmark-embed td:nth-child(2) {
  align-self: center;
  grid-column: 2 / -1;
}

.semaphore-benchmark-embed td:nth-child(n+3) {
  border-top: 1px solid #e5e7eb;
  padding-top: 0.5rem;
}

.semaphore-benchmark-embed td:nth-child(3) {
  grid-column: 1 / 3;
}

.semaphore-benchmark-embed td:nth-child(4) {
  grid-column: 3 / 4;
}

.semaphore-benchmark-embed td:nth-child(5) {
  grid-column: 4 / 5;
}
Enter fullscreen mode Exit fullscreen mode

}

@container (max-width: 30rem) {
.semaphore-benchmark-embed tr {
grid-template-columns: 2rem repeat(2, minmax(0, 1fr));
}

.semaphore-benchmark-embed td:nth-child(2) {
  grid-column: 2 / -1;
}

.semaphore-benchmark-embed td:nth-child(3) {
  grid-column: 1 / 3;
}

.semaphore-benchmark-embed td:nth-child(4) {
  grid-column: 3 / 4;
}

.semaphore-benchmark-embed td:nth-child(5) {
  grid-column: 1 / -1;
}
Enter fullscreen mode Exit fullscreen mode

}

@media (max-width: 57.5rem) {
.semaphore-benchmark-embed .chart-card {
padding: 1.5rem;
}

.semaphore-benchmark-embed th,
.semaphore-benchmark-embed td {
  padding: 0.75rem;
}
Enter fullscreen mode Exit fullscreen mode

}

@media (max-width: 42rem) {
.semaphore-benchmark-embed .chart-card {
padding: 1.25rem;
}

.semaphore-benchmark-embed .benchmark-table-wrap {
  overflow-x: visible;
}

.semaphore-benchmark-embed .benchmark-table,
.semaphore-benchmark-embed thead,
.semaphore-benchmark-embed tbody,
.semaphore-benchmark-embed tr,
.semaphore-benchmark-embed th,
.semaphore-benchmark-embed td {
  display: block;
  width: 100%;
}

.semaphore-benchmark-embed thead {
  clip: rect(0 0 0 0);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

.semaphore-benchmark-embed tbody {
  display: grid;
  gap: 0.625rem;
}

.semaphore-benchmark-embed tr {
  border: 1px solid #e5e7eb;
  border-radius: 14px;
  display: grid;
  gap: 0.5rem 0.625rem;
  grid-template-columns: 2rem repeat(3, minmax(0, 1fr));
  padding: 0.625rem;
}

.semaphore-benchmark-embed td {
  align-items: start;
  border-bottom: 0;
  display: block;
  min-width: 0;
  padding: 0;
  width: auto;
}

.semaphore-benchmark-embed td:nth-child(1),
.semaphore-benchmark-embed td:nth-child(2),
.semaphore-benchmark-embed td:nth-child(3),
.semaphore-benchmark-embed td:nth-child(4),
.semaphore-benchmark-embed td:nth-child(5) {
  width: auto;
}

.semaphore-benchmark-embed td::before {
  color: rgba(13, 20, 33, 0.62);
  content: attr(data-label);
  display: block;
  font-size: var(--font-down-2);
  font-weight: 800;
  margin-bottom: 0.1875rem;
  text-transform: uppercase;
}

.semaphore-benchmark-embed td.rank-cell {
  align-self: center;
  background: var(--color-cream);
  border-radius: 999px;
  display: grid;
  font-size: var(--font-down-1);
  height: 2rem;
  place-items: center;
  width: 2rem;
}

.semaphore-benchmark-embed .rank-cell::before,
.semaphore-benchmark-embed td:nth-child(2)::before {
  content: none;
}

.semaphore-benchmark-embed td:nth-child(2) {
  align-self: center;
  grid-column: 2 / -1;
}

.semaphore-benchmark-embed td:nth-child(n+3) {
  border-top: 1px solid #e5e7eb;
  padding-top: 0.5rem;
}

.semaphore-benchmark-embed td:nth-child(3) {
  grid-column: 1 / 3;
}

.semaphore-benchmark-embed td:nth-child(4) {
  grid-column: 3 / 4;
}

.semaphore-benchmark-embed td:nth-child(5) {
  grid-column: 4 / 5;
}
Enter fullscreen mode Exit fullscreen mode

}

@media (max-width: 30rem) {
.semaphore-benchmark-embed tr {
grid-template-columns: 2rem repeat(2, minmax(0, 1fr));
}

.semaphore-benchmark-embed td:nth-child(2) {
  grid-column: 2 / -1;
}

.semaphore-benchmark-embed td:nth-child(3) {
  grid-column: 1 / 3;
}

.semaphore-benchmark-embed td:nth-child(4) {
  grid-column: 3 / 4;
}

.semaphore-benchmark-embed td:nth-child(5) {
  grid-column: 1 / -1;
}
Enter fullscreen mode Exit fullscreen mode

}

CI Benchmark Ranking


  <table>
    <thead>
      <tr>
        <th>Rank</th>
        <th>Tool</th>
        <th>Avg Build Time</th>
        <th>Cost per Run</th>
        <th>vs. Semaphore (Speed)</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td><span></span>Semaphore <span>Best</span></td>
        <td>5m 01s</td>
        <td>$0.04</td>
        <td>—</td>
      </tr>
      <tr>
        <td>2</td>
        <td><span></span>Buildkite</td>
        <td>7m 15s</td>
        <td>$0.09</td>
        <td>+45% slower</td>
      </tr>
      <tr>
        <td>3</td>
        <td><span></span>GitHub Actions</td>
        <td>9m 44s</td>
        <td>$0.06</td>
        <td>+94% slower</td>
      </tr>
      <tr>
        <td>4</td>
        <td><span></span>GitLab CI</td>
        <td>11m 15s</td>
        <td>$0.11</td>
        <td>+125% slower</td>
      </tr>
      <tr>
        <td>5</td>
        <td><span></span>CircleCI</td>
        <td>13m 18s</td>
        <td>$0.08</td>
        <td>+165% slower</td>
      </tr>
    </tbody>
  </table>
Enter fullscreen mode Exit fullscreen mode

.semaphore-benchmark-embed {
--font-up-15: 6rem;
--font-up-13: 4.624rem;
--font-up-11: 3.653rem;
--font-up-9: 2.887rem;
--font-up-7: 2.281rem;
--font-up-6: 2.027rem;
--font-up-5: 1.802rem;
--font-up-4: 1.602rem;
--font-up-2: 1.266rem;
--font-up-1: 1.125rem;
--font-root: 1rem;
--font-down-1: 0.889rem;
--font-down-2: 0.79rem;
--font-down-3: 0.702rem;
--font-down-4: 0.624rem;

--color-cream: #F7F3EC;
--color-yellow: #FFD517;
--color-orange: #FFAF17;
--color-purple: #A74DC3;
--color-blue: #2865DE;
--color-ink: #0D1421;
--color-green: #16A34A;

box-sizing: border-box;
color: var(--color-ink);
container-type: inline-size;
font-family: inherit;
width: 100%;
Enter fullscreen mode Exit fullscreen mode

}

.semaphore-benchmark-embed *,
.semaphore-benchmark-embed *::before,
.semaphore-benchmark-embed *::after {
box-sizing: inherit;
}

.semaphore-benchmark-embed .charts {
display: grid;
gap: 1.75rem;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 24rem), 1fr));
width: 100%;
}

.semaphore-benchmark-embed .chart-card {
background: #fff;
border-color: #c8cbd0;
border-style: solid;
border-width: 1px;
border-top-left-radius: 20px;
border-top-right-radius: 20px;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
min-width: 0;
padding: 2rem;
}

.semaphore-benchmark-embed .chart-title {
font-size: var(--font-down-1);
font-weight: 800;
letter-spacing: 0;
margin: 0 0 1.75rem;
text-transform: uppercase;
}

.semaphore-benchmark-embed .bar-row {
align-items: center;
display: flex;
gap: 1rem;
margin: 0 0 1.125rem;
}

.semaphore-benchmark-embed .bar-row:last-child {
margin-bottom: 0;
}

.semaphore-benchmark-embed .bar-label {
align-items: center;
color: var(--color-ink);
display: flex;
flex: 0 0 8.25rem;
font-size: var(--font-down-1);
font-weight: 600;
gap: 0.5rem;
min-width: 0;
}

.semaphore-benchmark-embed .dot {
border-radius: 50%;
flex: 0 0 0.625rem;
height: 0.625rem;
box-shadow: 0 0 0 0.25rem rgba(13, 20, 33, 0.05);
width: 0.625rem;
}

.semaphore-benchmark-embed .bar-track {
background: var(--color-cream);
border-radius: 999px;
flex: 1 1 auto;
height: 1rem;
min-width: 4rem;
overflow: hidden;
position: relative;
}

.semaphore-benchmark-embed .bar-track::after {
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.42), transparent);
content: "";
inset: 0;
pointer-events: none;
position: absolute;
}

.semaphore-benchmark-embed .bar-fill {
animation: semaphore-bar-grow 900ms cubic-bezier(0.22, 1, 0.36, 1) both;
border-radius: inherit;
height: 100%;
transform-origin: left center;
width: var(--bar-width);
}

.semaphore-benchmark-embed .bar-value {
color: var(--color-ink);
flex: 0 0 5.75rem;
font-size: var(--font-down-1);
font-weight: 700;
text-align: right;
}

.semaphore-benchmark-embed .color-semaphore,
.semaphore-benchmark-embed .cost-semaphore {
background: var(--color-blue);
}

.semaphore-benchmark-embed .color-github,
.semaphore-benchmark-embed .cost-github {
background: var(--color-yellow);
}

.semaphore-benchmark-embed .color-buildkite,
.semaphore-benchmark-embed .cost-buildkite {
background: var(--color-orange);
}

.semaphore-benchmark-embed .color-gitlab,
.semaphore-benchmark-embed .cost-gitlab {
background: var(--color-purple);
}

.semaphore-benchmark-embed .color-circleci,
.semaphore-benchmark-embed .cost-circleci {
background: var(--color-ink);
}

.semaphore-benchmark-embed .badge-fastest,
.semaphore-benchmark-embed .badge-cheapest {
background: var(--color-green);
border-radius: 999px;
color: #fff;
display: inline-block;
font-size: var(--font-down-3);
font-weight: 800;
letter-spacing: 0;
line-height: 1;
margin-left: 0.5rem;
padding: 0.3125rem 0.625rem;
box-shadow: 0 0.375rem 0.875rem rgba(22, 163, 74, 0.24);
text-transform: uppercase;
vertical-align: middle;
white-space: nowrap;
}

@keyframes semaphore-bar-grow {
from {
transform: scaleX(0);
}

to {
  transform: scaleX(1);
}
Enter fullscreen mode Exit fullscreen mode

}

@media (prefers-reduced-motion: reduce) {
.semaphore-benchmark-embed .bar-fill {
animation: none;
}
}

@container (max-width: 46rem) {
.semaphore-benchmark-embed .charts {
grid-template-columns: 1fr;
}
}

@container (max-width: 30rem) {
.semaphore-benchmark-embed .chart-card {
padding: 1.25rem;
}

.semaphore-benchmark-embed .bar-row {
  align-items: stretch;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.5rem 0.75rem;
}

.semaphore-benchmark-embed .bar-label {
  flex-basis: auto;
}

.semaphore-benchmark-embed .bar-track {
  grid-column: 1 / -1;
  grid-row: 2;
}

.semaphore-benchmark-embed .bar-value {
  flex-basis: auto;
  white-space: nowrap;
}
Enter fullscreen mode Exit fullscreen mode

}

@media (max-width: 42rem) {
.semaphore-benchmark-embed .chart-card {
padding: 1.25rem;
}

.semaphore-benchmark-embed .bar-row {
  align-items: stretch;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.5rem 0.75rem;
}

.semaphore-benchmark-embed .bar-label {
  flex-basis: auto;
}

.semaphore-benchmark-embed .bar-track {
  grid-column: 1 / -1;
  grid-row: 2;
}

.semaphore-benchmark-embed .bar-value {
  flex-basis: auto;
  white-space: nowrap;
}
Enter fullscreen mode Exit fullscreen mode

}

  Average Build Time (minutes)


    <span></span>Semaphore



    5m 01s <span>Fastest</span>



    <span></span>Buildkite



    7m 15s



    <span></span>GitHub Actions



    9m 44s



    <span></span>GitLab



    11m 15s



    <span></span>CircleCI



    13m 18s




  Cost per Job (USD)


    <span></span>Semaphore



    $0.04 <span>Cheapest</span>



    <span></span>GitHub Actions



    $0.06



    <span></span>CircleCI



    $0.08



    <span></span>Buildkite



    $0.09



    <span></span>GitLab



    $0.11
Enter fullscreen mode Exit fullscreen mode

1. Semaphore — Fastest and Cheapest

Avg build time: 5m 01s

Cost per run: $0.04

Machine used: f1-standard-2 (2 vCPU, 8 GB RAM)

Semaphore came in first on both speed and cost. Its pipelines finished in just over five minutes — nearly half the time of GitHub Actions and almost a third of CircleCI. At $0.04 per job, it’s also the cheapest option tested.

Semaphore uses ephemeral VMs spun up fresh for every job, which eliminates environment drift and makes test results reproducible. It supports both a fully managed cloud offering and self-hosted agents, and its YAML schema is strict enough to be reliably generated by AI tools.

Best for: Teams that want fast, predictable pipelines without managing infrastructure. Particularly strong for Ruby, Go, and Node.js workloads. The open source enterprise edition is available for free for companies under $5M ARR with 50 users.

Pricing: $0.0075/min → semaphore.io/pricing

2. Buildkite — Fast, But Pricier Than It Looks

Avg build time: 7m 15s

Cost per run: $0.09

Machine used: LINUX_AMD64_2X4 (2 vCPU, 4 GB RAM)

Buildkite is the second-fastest platform in this benchmark, finishing 44.86% slower than Semaphore but well ahead of GitHub Actions and GitLab. It follows a hybrid model: Buildkite orchestrates pipelines, but you supply the compute (your own agents on EC2, GKE, bare metal, etc.).

That architecture gives you full infrastructure control and can be cost-effective at scale if you already run your own servers — but it adds operational overhead. The $0.09 per run figure reflects Buildkite’s managed compute pricing ($0.013/min), which is the most expensive per-minute rate in this benchmark. However, compute costs are only part of the picture.

The hidden cost: per-seat fees. Buildkite’s Pro plan (required for SSO, priority support, and 1-year build retention) charges $30 per active user per month, on top of all compute. For a team of 10 engineers, that’s $300/month in platform fees before a single build runs. At 20 engineers, $600/month — before compute. This makes Buildkite significantly more expensive at team scale than the per-run figures alone suggest.

Best for: Larger engineering teams with existing infrastructure who want fine-grained control over their runners. Less suitable for smaller teams that don’t want to manage agents.

Pricing: $0.013/min (compute) + $30/active user/month (Pro plan)

Avg build time: 9m 44s

Cost per run: $0.06

Machine used: ubuntu-latest (2 vCPU, 7 GB RAM)

GitHub Actions is the most widely adopted CI/CD platform, largely because it ships with every GitHub repository. The integration is seamless and the marketplace of third-party actions is vast.

However, in benchmarks it’s 94% slower than Semaphore on the same workload. At scale — say, a million build minutes — that translates to over 15,670 extra engineering hours waiting for pipelines to finish. GitHub Actions also made headlines in early 2026 for a pricing restructure that frustrated many teams and accelerated migration to alternatives.

Best for: Teams already on GitHub who want zero-friction CI setup and aren’t yet optimizing for pipeline speed or cost. Less suitable once you’re running dozens of daily pipeline runs and build time is a bottleneck.

Pricing: $0.0060/min

4. GitLab CI — Integrated, But Expensive at Scale

Avg build time: 11m 15s

Cost per run: $0.11

Machine used: saas-linux-small-amd64 (2 vCPU, 8 GB RAM)

GitLab CI is deeply integrated with GitLab’s broader DevOps platform — from source control to security scanning to deployment. If your team already lives in GitLab, CI/CD is a natural add-on.

Performance-wise, it came in fourth in this benchmark at 11m 15s — 124% slower than Semaphore. The per-run cost is the highest of all five platforms at $0.11 per job ($0.01/min), making it the most expensive option at scale. At a million build minutes, you’d be paying meaningfully more than with any competitor.

Best for: Teams heavily invested in the GitLab ecosystem (merge requests, security, releases) who need tight DevOps integration in one product. The built-in security scanning features are a genuine differentiator.

Pricing: $0.0100/min

5. CircleCI — Slowest in This Benchmark

Avg build time: 13m 18s

Cost per run: $0.08

Machine used: Docker medium (2 vCPU, 4 GB RAM)

CircleCI has been a long-time favourite in the CI/CD space and has a mature feature set — parallelism, test splitting, orbs for reusable config. In this benchmark, however, it was the slowest platform, finishing 165% behind Semaphore. At a million build minutes, that’s 27,519 extra hours of wait time compared to running the same workload on Semaphore.

One caveat: CircleCI’s Docker medium machine provides 4 GB RAM vs Semaphore’s 8 GB — hardware constraints likely contributed to the timing gap. That said, the 4 GB tier is CircleCI’s standard entry-level machine, making it the realistic comparison point for most teams.

Best for: Teams that have invested heavily in CircleCI’s orb ecosystem and parallelism configuration. Worth revisiting pricing and speed benchmarks if you’re scaling build volume.

Pricing: $0.0060/min

The Scale Problem: What Slow Pipelines Actually Cost

Build time differences feel abstract until you multiply them across a real engineering team. Based on 1,000,000 build minutes run on Semaphore (our fastest baseline):

.semaphore-benchmark-embed {
--font-down-1: 0.889rem;
--font-down-3: 0.702rem;

--color-cream: #F7F3EC;
--color-yellow: #FFD517;
--color-orange: #FFAF17;
--color-purple: #A74DC3;
--color-ink: #0D1421;

box-sizing: border-box;
color: var(--color-ink);
container-type: inline-size;
font-family: inherit;
width: 100%;
Enter fullscreen mode Exit fullscreen mode

}

.semaphore-benchmark-embed *,
.semaphore-benchmark-embed *::before,
.semaphore-benchmark-embed *::after {
box-sizing: inherit;
}

.semaphore-benchmark-embed .chart-card {
background: #fff;
border-color: #c8cbd0;
border-style: solid;
border-width: 1px;
border-radius: 20px;
min-width: 0;
padding: 2rem;
}

.semaphore-benchmark-embed .chart-title {
font-size: var(--font-down-1);
font-weight: 800;
letter-spacing: 0;
margin: 0 0 1.75rem;
text-transform: uppercase;
}

.semaphore-benchmark-embed .bar-row {
align-items: center;
display: flex;
gap: 1rem;
margin: 0 0 1.125rem;
}

.semaphore-benchmark-embed .bar-row:last-child {
margin-bottom: 0;
}

.semaphore-benchmark-embed .bar-label {
align-items: center;
color: var(--color-ink);
display: flex;
flex: 0 0 9.5rem;
font-size: var(--font-down-1);
font-weight: 600;
gap: 0.5rem;
min-width: 0;
}

.semaphore-benchmark-embed .dot {
border-radius: 50%;
box-shadow: 0 0 0 0.25rem rgba(13, 20, 33, 0.05);
flex: 0 0 0.625rem;
height: 0.625rem;
width: 0.625rem;
}

.semaphore-benchmark-embed .bar-track {
background: var(--color-cream);
border-radius: 999px;
flex: 1 1 auto;
height: 1rem;
min-width: 4rem;
overflow: hidden;
position: relative;
}

.semaphore-benchmark-embed .bar-track::after {
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.42), transparent);
content: "";
inset: 0;
pointer-events: none;
position: absolute;
}

.semaphore-benchmark-embed .bar-fill {
animation: semaphore-bar-grow 900ms cubic-bezier(0.22, 1, 0.36, 1) both;
border-radius: inherit;
height: 100%;
transform-origin: left center;
width: var(--bar-width);
}

.semaphore-benchmark-embed .bar-value {
color: var(--color-ink);
flex: 0 0 7.75rem;
font-size: var(--font-down-1);
font-weight: 700;
text-align: right;
}

.semaphore-benchmark-embed .color-github {
background: var(--color-yellow);
}

.semaphore-benchmark-embed .color-buildkite {
background: var(--color-orange);
}

.semaphore-benchmark-embed .color-gitlab {
background: var(--color-purple);
}

.semaphore-benchmark-embed .color-circleci {
background: var(--color-ink);
}

@keyframes semaphore-bar-grow {
from {
transform: scaleX(0);
}

to {
  transform: scaleX(1);
}
Enter fullscreen mode Exit fullscreen mode

}

@media (prefers-reduced-motion: reduce) {
.semaphore-benchmark-embed .bar-fill {
animation: none;
}
}

@container (max-width: 30rem) {
.semaphore-benchmark-embed .chart-card {
padding: 1.25rem;
}

.semaphore-benchmark-embed .bar-row {
  align-items: stretch;
  display: grid;
  gap: 0.5rem 0.75rem;
  grid-template-columns: minmax(0, 1fr) auto;
}

.semaphore-benchmark-embed .bar-label {
  flex-basis: auto;
}

.semaphore-benchmark-embed .bar-track {
  grid-column: 1 / -1;
  grid-row: 2;
}

.semaphore-benchmark-embed .bar-value {
  flex-basis: auto;
  white-space: nowrap;
}
Enter fullscreen mode Exit fullscreen mode

}

@media (max-width: 42rem) {
.semaphore-benchmark-embed .chart-card {
padding: 1.25rem;
}

.semaphore-benchmark-embed .bar-row {
  align-items: stretch;
  display: grid;
  gap: 0.5rem 0.75rem;
  grid-template-columns: minmax(0, 1fr) auto;
}

.semaphore-benchmark-embed .bar-label {
  flex-basis: auto;
}

.semaphore-benchmark-embed .bar-track {
  grid-column: 1 / -1;
  grid-row: 2;
}

.semaphore-benchmark-embed .bar-value {
  flex-basis: auto;
  white-space: nowrap;
}
Enter fullscreen mode Exit fullscreen mode

}

Extra Pipeline Hours vs. Semaphore


  <span></span>Buildkite



  +7,420 hours



  <span></span>GitHub Actions



  +15,670 hours



  <span></span>GitLab CI



  +20,709 hours



  <span></span>CircleCI



  +27,519 hours
Enter fullscreen mode Exit fullscreen mode

These aren’t just clock hours — they’re developer hours spent waiting for green checkmarks before merging, deploying, or moving to the next task. For a team of 20 engineers shipping 50+ builds a day, the difference between a 5-minute pipeline and a 13-minute pipeline is real, compounding time lost every single workday.

How to Choose

  • Go with Semaphore if speed and cost efficiency are priorities and you want managed infrastructure without maintenance overhead. Especially strong for teams migrating from GitHub Actions or CircleCI.
  • Go with Buildkite if you have existing server infrastructure and want to run your own agents with platform-level orchestration.
  • Go with GitHub Actions if you’re a small team on GitHub and don’t yet have volume high enough for pipeline speed to matter.
  • Go with GitLab CI if you’re fully embedded in the GitLab platform and value security scanning and DevOps integration over raw pipeline speed.
  • Go with CircleCI if you have complex parallelism setups built around CircleCI’s orb ecosystem and a migration isn’t feasible in the short term.

Methodology Notes

Full benchmark details — including raw run logs, machine specs, and configuration files — are published in the original Semaphore CI/CD Benchmark report. All tests were run by the Semaphore team; we recommend running your own benchmark against your specific workload before making a final decision.

Want to try Semaphore on your own codebase? You can create a project for free and run the benchmark yourself — the configuration files are public.

The post Best CI/CD Tools in 2026: Performance and Cost Compared appeared first on Semaphore.

Top comments (0)