Skip to content

Pull-Based vs. Push-Based Deploys

Module 15 (CI/CD) covers a pipeline that builds, tests, and deploys a change — typically by pushing it out: a runner authenticates to the target environment and applies the change from outside. GitOps flips that direction. This page covers exactly what changes when a deploy becomes pull-based.

TL;DR — in 30 seconds:

  • Push-based (traditional CI/CD): a pipeline runner, outside the target environment, authenticates in and applies the change — the runner needs deploy credentials to the target.
  • Pull-based (GitOps): an operator running inside the target environment pulls the desired state from git and applies it locally — nothing outside the environment needs deploy credentials to it.
  • The practical payoff is a smaller credential attack surface: a compromised CI runner in a push model can deploy directly; in a pull model, the worst it can do is merge a bad change to git, which still goes through review and the operator's own reconciliation.

1. Two directions, one goal

flowchart LR
    subgraph Push["Push-based (traditional CI/CD)"]
        P1["CI runner"] -->|"authenticates in,<br/>applies change"| P2["Target environment"]
    end
    subgraph Pull["Pull-based (GitOps)"]
        G1["Git repo"] <-.->|"operator pulls,<br/>compares, applies"| G2["Operator<br/>(inside target environment)"]
    end

Both models want the same outcome — the target environment matches the intended change. The difference is who initiates the connection and who holds the credentials:

Push-based CI/CD Pull-based GitOps
Who applies the change The CI runner, from outside An operator, running inside the target
Where deploy credentials live On the CI runner / pipeline Only inside the target environment
What a compromised pipeline can do Deploy directly to the target Merge a change to git (still reviewable)
How you know what's live right now Check pipeline logs / history Read the git repo

2. Why the credential difference matters

In a push model, the CI system needs standing credentials that can write to production — that's a real, valuable target: if the pipeline (or its secrets) is compromised, an attacker can deploy directly.

In a pull model, the operator's credentials never leave the target environment — nothing external holds a key that can write to it. A compromised CI pipeline can still merge a malicious change to the GitOps repo, but that merge is a normal, reviewable git operation (a PR, a diff, a commit author) — not a silent direct deploy. It doesn't eliminate risk, but it narrows what a compromised pipeline can do and makes the action visible in git history.

Common gotchas

  • Assuming pull-based means "no CI/CD is involved." Fix: CI/CD still builds, tests, and — in a GitOps flow — opens the PR that updates the desired state in git. What moves is the deploy step, not the whole pipeline.
  • Giving the GitOps operator broader permissions than it needs. Fix: pull-based reduces external credential exposure, but the in-cluster operator itself still needs scoped, least-privilege access to the resources it manages — it's not a free pass to over-permission it.
Check yourself — in a push-based pipeline, a stolen CI secret lets an attacker deploy directly to production. What's different about the equivalent attack in a pull-based GitOps setup?

A stolen CI secret in a pull-based setup doesn't grant deploy access to the target environment at all — the CI pipeline never held those credentials. The attacker's best option is merging a malicious change to the GitOps repo, which still goes through the same review/PR process as any other change and is visible in git history, rather than an invisible direct deploy.

Done when: you can state, in one sentence, which side holds the deploy credentials in each model and why that difference narrows what a compromised pipeline can do.