Azure Pipelines vs GitLab CI/CD

Azure Pipelines suits teams that keep Azure Repos and Azure Boards. Self-managed GitLab CI/CD suits teams that want CI, repositories and planning on one platform they run in their own infrastructure.

On this page

Which should you choose: Azure Pipelines or GitLab CI/CD on self-managed GitLab?

Keep Azure Pipelines if your repositories and boards stay in Azure DevOps and your builds depend on Microsoft tooling or Windows agents. Move to GitLab CI/CD on self-managed GitLab if you want source, issues, merge requests and pipelines on one platform you run, or if your environment must work without internet access. The decision turns on two questions: whether Azure Repos and Azure Boards move too, and whether your team has the capacity to operate a GitLab instance with its own upgrades, backups and runners. Azure Pipelines fits well where the rest of the delivery chain is Microsoft: Azure Repos for code, Azure Boards for work tracking, Azure service connections for deployments, and Windows or .NET builds that need Microsoft-hosted or self-hosted Windows agents. Its value is the integration already in place. Self-managed GitLab fits where you want one system for repositories, CI/CD, package and container registries and security scanning. GitLab documents running self-managed instances in offline, air-gapped environments, and its Ultimate tier adds the security and compliance features. Before committing, confirm which GitLab tier covers the CI features you need, since the pricing page places advanced CI/CD in Premium and security scanning in Ultimate. If you only move CI, the pipelines still need their repositories to be reachable from GitLab Runner, and the work items and Azure Boards links stay behind. Ask a migration partner or your own platform team to map which Azure Pipelines variables, service connections and environment approvals become GitLab CI/CD variables, protected environments and runner tags, and plan how secrets get re-entered, because Azure DevOps does not return secret values for export. Plan for the operating load too: GitLab upgrades must pass through required upgrade stops, and the reference architectures for larger user counts run stateful services outside Kubernetes.

Which scenarios favor each option

This table compares Azure Pipelines and self-managed GitLab CI/CD across common situations, naming the better fit and the condition that drives each choice. Read each row against your own repository location, hosting rules and Microsoft tooling dependencies, and treat the first matching condition as the deciding factor.

ScenarioBetter fitCondition that drives the choice
Repositories stay in Azure ReposAzure PipelinesMoving CI alone to GitLab means pipelines would build code hosted elsewhere, which adds integration work and a second system to operate.
Team wants all DevOps on one forgeGitLab CI/CDRepositories, merge requests, issues, registry and CI share one administration model, but moving boards and repositories is a separate project.
Air-gapped or strictly regulated hostingGitLab CI/CDSelf-managed GitLab documents offline, air-gapped operation, so confirm the offline scope for each feature your pipelines need.
Windows and .NET builds on Microsoft toolingAzure PipelinesHosted and self-hosted Windows agents, Visual Studio tasks and Azure service connections are built around the Microsoft stack; GitLab Runner needs Windows runners you maintain.
Classic release pipelines in useGitLab CI/CDClassic releases need a redesign either way; GitLab environments and protected manual jobs map to approval stages, but each approval rule must be rebuilt.
No one on the team operates GitLabAzure PipelinesSelf-managed GitLab includes PostgreSQL, Gitaly and runner fleets to run, so budget for operator skills before choosing it.
Existing Azure DevOps approvals and boardsAzure PipelinesApprovals, work item links and dashboards are tied to Azure DevOps, and their replacements in GitLab need a migration plan for each one.
Kubernetes-centric delivery with strong self-hosting needsGitLab CI/CDGitLab runners and the Cloud Native Hybrid layout keep stateful services on VMs or managed services, so confirm the target topology with GitLab documentation before committing.

Where your pipelines, secrets and data live

Moving CI from Azure Pipelines to self-managed GitLab changes where build logs, secrets, artifacts and identities sit. The cards below cover the decisions that follow from that change, from licensing and installation to the evidence an assessor will ask for.

Open-core licensing boundaries

GitLab's source is open core. Code outside the ee/ directory is available under the MIT Expat license, while code inside it falls under the GitLab Enterprise Edition license. Your legal team should confirm which features your tier depends on and read the license terms that apply to them before you standardize on the platform.

Choosing an installation method

GitLab can be installed from the Linux package, the Helm chart, the GitLab Operator, Docker or source. The Linux package bundles PostgreSQL, Redis and Sidekiq and is described as the most mature method. Pick the method your operations team can patch and back up, and confirm which method your upgrade path and support plan assume.

Keeping stateful services off Kubernetes

GitLab's reference architectures state that running PostgreSQL and Redis inside Kubernetes is not supported. The Cloud Native Hybrid architecture runs stateless components on Kubernetes and places stateful services on VMs or managed services. Plan that split early, because it changes your node pools, storage budget and backup design.

Secrets and variables on migration

CI secret values generally cannot be read back from Azure Pipelines or from other hosted CI services. Expect to re-create secret variables and service connections in GitLab and rotate the underlying credentials as part of the cutover. Record which secrets were recreated, by whom and when, so the change is traceable.

Identity and access control

Decide whether GitLab authenticates users through its own accounts or through your existing identity provider, and how group and project roles map to the teams that currently hold Azure DevOps permissions. Confirm which authentication methods your edition supports and how runner registration tokens and deploy keys are scoped.

Evidence for compliance assessments

Your assessor will ask for records of who can change pipelines, where logs and artifacts are retained, how backups are tested and how the platform is patched. DeployOpen can prepare these controls and evidence, but it does not issue audit reports or attestations. Independent auditors and certification bodies make that determination.

How Azure agents and GitLab Runner executors differ in day-to-day use

The core difference is where the work runs and who controls the capacity. In Azure Pipelines, a job is routed to a pool of agents, and the pool decides which machine picks up the work based on demand for its parallel jobs. Microsoft-hosted agents are billed by parallel job, so every additional concurrent pipeline run is a line item that grows with team size and build frequency. In GitLab, a runner registers with the GitLab instance and pulls jobs that match its tags, and the executor (Docker, Kubernetes, shell or others) defines how each job is isolated. Routing is controlled by tags in the .gitlab-ci.yml file and by runner scope, which lets you dedicate runners to a project group or to a protected branch.

Self-hosted runners remove the per-job metering, but they move the cost into capacity and operations. Your team must size the runner fleet, decide how many concurrent jobs each host can take, autoscale executors (for Kubernetes, check how the runner's autoscaling settings map to your cluster quotas), patch runner hosts and rotate runner tokens. Confirm with your GitLab administrators how runner registration is restricted, and whether jobs for regulated projects must run only on runners in your network. Also confirm the Windows and macOS support you need, since Azure agent images cover platforms that a Linux-container executor model may not match one for one.

Before you commit, run a short trial with your heaviest pipelines. Measure queue time at peak, the number of concurrent jobs your busiest hours require, and how long a runner host takes to recover after a failed update. Those numbers, not the list price of the forge, determine whether the self-managed model is cheaper for your organization. Ask your vendor or implementation partner for a written capacity plan and a runbook covering runner upgrades, since GitLab releases a new minor version each month and runners should track the instance version.

What moving CI to GitLab involves

The sequence below takes Azure Pipelines definitions, secrets, run history and artifacts into self-managed GitLab CI/CD in an order that keeps builds running until each part is verified.

  1. Inventory pipelines, templates and dependencies

    List every Azure Pipelines definition, the YAML templates they extend, variable groups, environments, service connections, agent pools and the repositories each one builds. Someone who owns the Azure DevOps organization should do this, with input from the teams that own each application. It is done when every pipeline has an owner, a target repository and a note on which external tasks or extensions it depends on, so nothing is discovered during cutover.

  2. Decide what moves with the repositories

    Decide whether source repositories move to GitLab, stay in Azure Repos with GitLab CI reading them, or move later. Azure Boards work items are a separate decision, because GitLab issues and boards are not a one-to-one copy of Azure Boards. Platform leads and product owners should sign this off in writing. It is done when each repository and each board has a recorded destination.

  3. Import repositories into GitLab

    Import the repositories with GitLab's import and migrate tooling, then check branches, tags, commit history and branch protection settings against the source. The engineering team that owns each repository confirms the result. It is done when a sample of commits, tags and merge requests matches the source and the team signs off on the imported project.

  4. Convert YAML and rebuild environments and approvals

    Rewrite each Azure Pipelines YAML file as a .gitlab-ci.yml configuration, turning stages, jobs and templates into GitLab stages, jobs and includes. Recreate environments, deployment approvals and protected branch rules in GitLab, then run the pipelines against a non-production target. Pipeline engineers do the conversion and release managers confirm the approval flow. It is done when a non-production deployment passes through the same approval gates recorded in the inventory.

  5. Re-create secrets and runner configuration

    Azure Pipelines does not let you export secret variable values or service connection credentials, so each secret must be generated or retrieved again from its source system and entered into GitLab CI/CD variables or a secrets manager. Register GitLab Runners in your own infrastructure with executors that match the old agent pools. Security and platform teams should confirm that every secret was rotated where it is practical. It is done when each pipeline runs on a runner you control and no credential depends on the old Azure service connection.

  6. Export run history, logs and artifacts

    Export the run history, logs and build artifacts you need to keep for audit or rollback, because Azure Pipelines run data is not carried into GitLab automatically. Use the GitLab backup and restore guidance to plan how the new instance itself is protected, and store exported records in an archive that your retention policy controls. The compliance owner confirms which records must be kept and where. It is done when the archive can be opened and the retention decision is written down.

  7. Cut over and run both systems in parallel

    Switch the pipelines that were verified in non-production to GitLab, one application at a time, while keeping the Azure Pipelines definitions available for fallback until each cutover is stable. Watch failed runs, deployment results and runner capacity during this period. The release manager closes each cutover. It is done when each application has deployed through GitLab at least once to production and the fallback path is no longer needed.

  8. Retire Azure Pipelines definitions and access

    Disable the old pipelines, remove service connections and agent pools that are no longer used, revoke access for users who no longer need it, and record the final state of the Azure DevOps organization. Confirm with the owner of the Azure DevOps subscription before anything is deleted. It is done when the inventory shows every pipeline as migrated or retired and the retirement record is filed with the platform team.

What drives the cost of self-managed GitLab against Azure Pipelines

The cost comparison turns on who pays for what. On the Azure side, the main recurring line is parallel jobs, which Microsoft bills for hosted and self-hosted pipelines, plus the agent machines you run yourself if you use self-hosted agents. On the GitLab side, the subscription is priced per user, with Free at 0 US dollars, Premium at 29 US dollars per user per month billed annually according to the GitLab pricing page, and Ultimate quoted on request. Premium is the tier that adds advanced CI/CD and priority support, so confirm which tier your pipeline features require before you assume Free is enough. Ultimate's security and compliance features are priced separately, so ask for it as its own line item.

The cost that moves most with the design is everything GitLab does not bill for. Your own infrastructure carries the GitLab instance itself, GitLab Runner hosts (the executors that run jobs), object storage for artifacts and container images, and the database and Redis services that the Linux package bundles. Upgrades are recurring work: GitLab requires passage through the required upgrade stops at x.2, x.5, x.8 and x.11, so plan for those windows instead of a single annual jump. Backups and restore tests recur as well, and the offline environment guidance adds effort if your instance cannot reach the internet. Staff time for administration, upgrade testing and runner capacity is usually the largest recurring cost, and it is the one most often left out of the comparison.

When you request a quote, ask for the per-user price by tier, the number of users you will license for, any Ultimate line items, and whether support tiers change the price. Ask the vendor or partner to state which infrastructure assumptions the estimate includes, such as runner count, storage growth and high availability. Confirm your expected number of users and the reference architecture that matches your size with GitLab's documentation before you compare totals. Your own check is to list each Azure line item (parallel jobs, agent VMs, storage) and map it to a GitLab line item, then add the staff hours for upgrades and backups to both sides so the comparison is complete.

Questions buyers ask before switching from Azure Pipelines to GitLab

How much effort and cost does switching from Azure Pipelines to GitLab CI/CD involve?

The cost comes from four components: the GitLab subscription, the infrastructure that runs GitLab and its runners, the migration work, and the people who operate the platform afterward. GitLab Free costs 0 US dollars and Premium costs 29 US dollars per user per month billed annually, according to the GitLab pricing page, with Ultimate priced on request. Migration effort is one-time, while licensing, hosting, runner compute and upgrade work recur. Effort rises with the number of pipelines, templates, service connections and environments, and with how many Azure DevOps features you depend on beyond CI. Ask any partner for a fixed-scope written quote that lists each component separately.

How long does a move from Azure Pipelines to GitLab take?

No duration is fixed for every team, because the answer depends on the inventory. The main drivers are the number of pipelines, how many YAML templates are shared across repositories, how many classic release pipelines still need to be redesigned, and how many secrets and service connections must be re-created by hand. Teams that run a short parallel period, where both systems build the same commits, usually need more time than a one-off cutover. Ask for a written timeline tied to a scoped inventory of your pipelines rather than a generic estimate.

What does our team need to provide for a GitLab CI/CD migration?

The work needs named owners from several groups, not only from the build team. You will need someone who knows each pipeline's purpose, a platform engineer to size and operate the GitLab instance and GitLab Runner fleet, a security owner to approve how deployment credentials are re-created, and an approver for each production environment. Plan for access to the Azure DevOps REST API for export, administrator rights on the target GitLab instance, and a place to host the runners. GitLab's reference architectures are sized by user count, so confirm your headcount and request rate before choosing a deployment size.

Can our own engineers do the migration without a partner?

Yes, many teams do, especially when the pipeline estate is small and the team already runs GitLab or Kubernetes. The harder parts are rarely the YAML: they are secret re-creation, environment approvals, self-hosted runner security, backup design and upgrade planning. Azure Pipelines secret values cannot be read back, so each one must be re-entered from its source system. An external partner is useful when you need a fixed scope, independent hardening, or documented evidence for a compliance assessment. DeployOpen does not issue audit reports or certifications; independent auditors and certification bodies do that work.

Do we have to move Azure Repos to GitLab to use GitLab CI/CD?

No, you do not have to move repositories to run pipelines on GitLab. GitLab CI/CD works with code in GitLab, and moving CI usually means moving repositories too, because GitLab pipelines are defined in the project that hosts them. Moving repositories is a separate decision with its own work: importing history, rewriting links in boards and pipelines, and retraining developers on merge requests. Azure Boards and Azure Repos are not CI features, so decide them together but track them as separate work items with their own cutover dates.

How are secrets and build artifacts handled when moving to GitLab?

Secrets and artifacts need separate plans because neither can be fully exported by default. Azure Pipelines secret variables and service connection values cannot be read back, so you must re-create them in GitLab's CI/CD variable store or an external secrets manager, using values from the source systems. Keep an inventory of which pipelines use each secret, rotate credentials you can no longer verify, and restrict who can read protected variables. For artifacts and run history, export what you need before decommissioning Azure Pipelines and decide retention on the GitLab side. Confirm the exact export options with your Azure DevOps administrator and the GitLab documentation for your version.

How do GitLab upgrades and the maintenance policy affect day-to-day operations?

Self-managed GitLab needs a planned upgrade routine. GitLab ships a major release yearly, a minor release on the third Thursday of each month and patch releases twice a month, and currently maintains 19.5, 19.4 and 19.3. Bug fixes go only to the current stable release, while security fixes also reach the previous two monthly releases, so you should stay on a supported version. Upgrades must pass through required upgrade stops, which since GitLab 17.5 fall at x.2, x.5, x.8 and x.11, for example 19.2, 19.5, 19.8 and 19.11. Budget recurring time for these upgrades, test them in a staging instance, and take a backup before each one.

How the choice differs by team type

Teams that already run Azure Boards, Azure Repos and Azure Pipelines together usually see the largest switching cost, because moving CI alone leaves the rest of the workflow in place. GitLab CI/CD fits when the organization is willing to move repositories, issues and approvals into GitLab as well, so that pipelines, merge requests and environments share one data model. If only the pipelines move, expect to keep Azure Repos or Azure Boards links, service connections and work item references working through integrations you must build and maintain.

  • Repository move scope: Confirm whether Azure Repos will move, or whether builds must keep pulling from Azure Repos during a transition.
  • Work item links: Check how commit and pull request links to Azure Boards items will be preserved or replaced.
  • Identity: Confirm how Microsoft Entra ID groups map to GitLab groups and roles on your self-managed instance.
  • Deployment targets: List every service connection and confirm the GitLab Runner executor that will reach each target.

Confirm these items with your Azure DevOps administrator and your GitLab account team before scoping the migration.

How DeployOpen helps you evaluate, implement or migrate

DeployOpen plans, implements, hardens, documents and supports self-hosted open-source platforms inside your own infrastructure, so a move from Azure Pipelines to self-managed GitLab CI/CD starts with a written scope. We can help you compare the two systems on your own pipelines before any decision is made.

How we scope

  • We review your Azure Pipelines YAML, templates, service connections and variable groups to define what the GitLab CI/CD scope covers.
  • The written scope names repositories, boards, runners, environments and approvals that move, and those that stay where they are.
  • Engagements are fixed-scope, with deliverables and timelines agreed in writing before any work starts.

How we build

  • We stand up a self-managed GitLab instance in your cloud account, data center or air-gapped network, with runners matched to your build needs.
  • We convert pipeline definitions into GitLab CI/CD configuration and test them against representative branches and deployment targets.
  • Secrets are re-created in GitLab from your own records, because values cannot be read back from Azure Pipelines to copy.

How we hand over

  • You receive configuration, runner setup, environment and approval design, and runbooks written for your own operations staff.
  • We document the cutover plan, rollback steps and the artifact and run history exports completed before the switch.
  • We walk your platform, security and release teams through the handover so they can operate the system independently.

How we support

  • Ongoing support, upgrades and continuous testing are available as retainers, so the instance keeps pace with GitLab's release cadence.
  • We can plan upgrades through the required upgrade stops and keep backups and restore tests aligned with your recovery targets.
  • Security testing of the pipelines and runners can be scheduled as part of a retainer, with findings tracked to closure.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.