DEV Community

Cover image for 🦊 GitLab Runners: Which Topology for Fastest Job Execution?
Benoit COUETIL πŸ’« for Zenika

Posted on • Edited on

🦊 GitLab Runners: Which Topology for Fastest Job Execution?

With multiple executor types availableβ€”from shared SaaS runners to Kubernetes clusters to single-server setupsβ€”understanding how each impacts job speed helps you make informed architectural decisions. Spoiler: the simplest topologies often deliver the fastest jobs.

Initial thoughts

Choosing the right GitLab Runner topology is crucial for fast job execution. With multiple executor types availableβ€”from shared SaaS runners to self-hosted solutionsβ€”understanding how each impacts job speed helps you make informed architectural decisions.

This article focuses on a single question: which runner topology executes jobs the fastest? We analyze different topologies through the lens of job execution phases, comparing the time overhead each infrastructure type adds before, during, and after script execution. Whether you're starting fresh or optimizing an existing setup, understanding these trade-offs is essential to minimize job duration.

πŸ“– Note: This article focuses on intrinsic speed characteristics. Some disadvantages mentioned here can be mitigated through configuration tricks (idle pools, spot instances, over-provisioning, etc.). For detailed pros/cons and mitigation strategies, see GitLab Runners Topologies: Pros and Cons.

Understanding job execution phases

From runner selection to final cleanup, every job goes through multiple technical phases. Understanding these phases is crucial to optimizing pipeline performance.

Here's a detailed breakdown of all the technical steps involved in running a single GitLab CI job:

Diagram

Each phase adds latency to job execution. The key to achieving fast pipelines is minimizing time spent in these overhead phases and focusing on actual script execution. Different runner topologies handle these phases very differently.

Comparing runner types

Let's analyze the performance characteristics of each GitLab Runner infrastructure type, examining how they handle the execution phases differently.

πŸ“Š Reading the charts: Throughout this article, the durations shown in Gantt diagrams are relative and illustrativeβ€”actual times vary based on project size, network conditions, and infrastructure specs. What matters is the color coding:

  • 🟒 Green: Faster than average across runner types
  • βšͺ Grey: Average performance
  • πŸ”΄ Red: Slower than average across runner types

GitLab Shared Runners (SaaS)

GitLab.com provides shared runners available to all users without any setup. While convenient, these runners compete for resources with thousands of other projects, making them the slowest option for job execution.

Topology: Shared SaaS infrastructure - all users share the same pool of runners and cache storage.

Diagram

Performance characteristics:

Diagram

Speed advantages:

  • βœ… No wait for infrastructure provisioning

Speed disadvantages:

  • ❌ Slowest overall performance (all resources shared)
  • ❌ Every job pulls images from scratch
  • ❌ Shared network bandwidth slows git operations
  • ❌ Unpredictable performance due to multi-tenancy
  • ❌ Slow artifact uploads/downloads

Best for: When speed is not a priority and zero maintenance is essential.

Kubernetes Executor (Fixed Cluster)

A fixed-size Kubernetes cluster provides consistent resources for CI jobs. While more complex to set up than shared runners, it offers better performance through image caching and dedicated resourcesβ€”though still limited by network-based cache and pod startup overhead.

Topology: Fixed-size cluster with shared remote cache (S3/MinIO).

Diagram

Performance characteristics:

Diagram

Speed advantages:

  • βœ… Fast when warm (images cached on nodes)
  • βœ… Pod creation relatively quick on existing nodes
  • βœ… Consistent performance with dedicated resources

Speed disadvantages:

  • ❌ Jobs queue when capacity is reached
  • ❌ Remote cache adds network latency
  • ❌ Pod startup overhead (even on warm nodes)

Best for: Teams with existing Kubernetes infrastructure where moderate speed is acceptable.

Kubernetes Executor (Autoscaling Cluster)

Autoscaling Kubernetes clusters dynamically add nodes when demand increases. This eliminates queuing issues but introduces significant cold-start delaysβ€”new nodes take time to provision, and each job starts with a fresh environment requiring full image pulls and git clones.

Topology: Cluster with autoscaler that adds/removes nodes based on load, pods distributed dynamically.

Diagram

Performance characteristics:

Diagram

Speed advantages:

  • βœ… No queue time when scaling up
  • βœ… Dedicated resources per job once running

Speed disadvantages:

  • ❌ Very slow cold starts (node provisioning 30s-2min)
  • ❌ Full image pulls on new nodes
  • ❌ Complete git clones on ephemeral pods
  • ❌ Remote cache network latency

Best for: Variable workloads where cold-start delays are acceptable trade-offs for unlimited capacity.

Mechanical racing foxes competing in a cyberpunk race

Docker Executor (Single Server)

A single server running Docker provides the sweet spot between isolation and performance. Containers start quickly when images are cached, git repositories are reused locally, and cache access is lightning-fast through the local filesystemβ€”all while maintaining job isolation.

Topology: Single server with Docker Engine - container isolation but shared local cache via volumes.

Diagram

Performance characteristics:

Diagram

Speed advantages:

  • βœ… Very fast local cache access (filesystem)
  • βœ… Image layers cached locally
  • βœ… Quick container startup when warm
  • βœ… Local git repository reuse
  • βœ… No network latency for cache

Speed disadvantages:

  • ❌ Jobs queue when server capacity is reached
  • ❌ Container overhead (minimal but present)

Best for: Teams needing container isolation with near-optimal speed.

Shell Executor (Single Server)

The shell executor is the fastest possible configurationβ€”no containers, no image pulls, no pod scheduling. Everything runs directly on the host system with instant access to local git repos and filesystem cache. The trade-off? No job isolation, requiring trust in your codebase.

Topology: Everything is local on a single server - runner, shell execution, and cache share the same filesystem.

Diagram

Performance characteristics:

Diagram

Speed advantages:

  • βœ… Absolute fastest (zero container overhead)
  • βœ… Instant cache access (direct filesystem)
  • βœ… Fastest git operations (local clones reused)
  • βœ… No image pulls ever
  • βœ… Immediate job start (no container creation)
  • βœ… Best optimization potential

Speed disadvantages:

  • ❌ Jobs queue when server capacity is reached

Best for: Maximum speed when job isolation is not required.

Docker Autoscaler (Fleeting)

Docker Autoscaler uses the Fleeting plugin system to spawn VMs on cloud providers. It dynamically provisions VMs when demand increases and terminates them when idle, providing unlimited capacity at the cost of cold-start delays.

Topology: Autoscaling VMs - plugin-based architecture supporting multiple cloud providers.

Diagram

Performance characteristics:

Diagram

Speed advantages:

  • βœ… No queue time (infinite capacity)
  • βœ… Dedicated resources once VM is ready

Speed disadvantages:

  • ❌ Slow cold starts (15+ seconds VM provisioning)
  • ❌ Full git clone on each VM
  • ❌ Full image pull on each VM
  • ❌ Cloud cache network latency

Best for: Variable workloads requiring autoscaling where cold-start delays are acceptable.

Job speed comparison summary

Here's a comprehensive comparison of job execution speed across all execution phases:

Legend: 🟒 Fast Β· βšͺ Medium Β· πŸ”΄ Slow

Runner Type Wait VM/Pod OS Git Script Cache Artifacts
GitLab Shared 🟒 🟒 πŸ”΄ πŸ”΄ πŸ”΄ πŸ”΄ πŸ”΄
K8S Fixed βšͺ 🟒 βšͺ βšͺ βšͺ βšͺ βšͺ
K8S Autoscaling 🟒 βšͺ πŸ”΄ πŸ”΄ 🟒 βšͺ βšͺ
Docker πŸ”΄ 🟒 βšͺ 🟒 πŸ”΄ 🟒 βšͺ
Shell πŸ”΄ 🟒 🟒 🟒 πŸ”΄ 🟒 βšͺ
Docker Autoscaler 🟒 πŸ”΄ πŸ”΄ πŸ”΄ 🟒 βšͺ βšͺ

Key insights:

  • GitLab Shared: Great for zero maintenance but slowest overall
  • K8S Fixed: Balanced approach with good warm performance
  • K8S Autoscaling: Best for variable loads but cold starts are slow
  • Docker Single Server: Fast local operations with isolation
  • Shell Single Server: Fastest local operations, best optimization potential
  • Docker Autoscaler: Maximum scalability but slowest cold starts

Recommendation: Shell or Docker executors for fastest jobs

After analyzing all runner types, Shell and Docker executors on single servers offer the fastest job execution for most teams.

Why single-server executors win on speed

1. Local everything = minimal latency

  • Git repositories cached locally
  • Dependencies and cache on local filesystem
  • No network round-trips for cache operations
  • Instant resource availability (no VM/pod provisioning)

2. Vertical scaling is underrated

  • Modern servers can handle dozens of concurrent jobs
  • SSD storage makes local caching extremely fast
  • RAM caching for frequently accessed data
  • CPU cores scale linearly for parallel jobs

3. Warm infrastructure advantage

  • Docker images already pulled and cached
  • Git repos incrementally fetched (not full clones)
  • Dependencies preserved between jobs
  • No cold-start penalties

Shell vs Docker trade-offs

Choose Shell when:

  • You need maximum speed
  • Your codebase is trusted
  • You can maintain consistent tooling
  • Security isolation is less critical
  • You want to push performance limits

Choose Docker when:

  • You need job isolation
  • Multiple projects with different dependencies
  • Security/multi-tenancy matters
  • Slightly slower speed is acceptable trade-off

The performance/price/maintenance sweet spot

πŸ“ˆ Vertical scalability compensates for the lack of horizontal scalability

πŸ’ͺ A properly sized server with local SSD can handle dozens of simultaneous jobs

πŸ’° Predictable costs: No per-job pricing, one server cost

πŸ”§ Low maintenance: Simple architecture, fewer moving parts

πŸ“– Reference: GitLab CI: The Majestic Single Server Runner

Wrapping up

Choosing the right GitLab Runner topology depends on your specific needs, but if minimizing job execution time is your primary concern, Shell or Docker executors on well-provisioned single servers consistently deliver the fastest jobs.

Key takeaways:

  1. Shared runners are great for getting started but have performance limitations due to multi-tenancy
  2. Kubernetes solutions offer good isolation and scalability but add network latency
  3. Single-server executors (Shell/Docker) provide the fastest local operations and best optimization potential
  4. Autoscaling solutions handle variable loads well but suffer from cold-start penalties
  5. Vertical scaling of single servers is often more effective than complex horizontal scaling

The comparison shows that while autoscaling solutions offer flexibility, a properly configured single-server runner often provides the best performance for teams with predictable workloads or those willing to size for peak capacity.

In the next article, we'll dive deep into extreme optimizations you can apply to Shell and Docker runners to push performance even furtherβ€”potentially achieving job times as low as 3 seconds on multi-million line codebases!

Mechanical racing fox crossing the finish line

Illustrations generated locally by Draw Things using Flux.1 [Schnell] model

Further reading

πŸ”€ Git / 🦊 GitLab

☸️ Kubernetes

πŸ“ Miscellaneous


This article was enhanced with the assistance of an AI language model to ensure clarity and accuracy in the content, as English is not my native language.

Top comments (0)