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%;
}
.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;
}
}
@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;
}
}
@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;
}
}
@media (max-width: 57.5rem) {
.semaphore-benchmark-embed .chart-card {
padding: 1.5rem;
}
.semaphore-benchmark-embed th,
.semaphore-benchmark-embed td {
padding: 0.75rem;
}
}
@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;
}
}
@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;
}
}
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>
.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%;
}
.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);
}
}
@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;
}
}
@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;
}
}
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
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)
3. GitHub Actions — Popular, But Slower Than You’d Think
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%;
}
.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);
}
}
@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;
}
}
@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;
}
}
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
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)