Pakkit.net
← Back to blog

Automation

Push or Pull: How Configuration Reaches a Fleet

There are two fundamental shapes for getting configuration onto a fleet of machines — a controller that pushes to them, or an agent on each that pulls — and the choice quietly determines how you scale, how you handle drift, and what happens to a machine that was asleep when the change went out.

  • Automation
  • Infrastructure
  • Configuration Management
  • Operations

Once you’re managing more than a handful of machines, “how does config actually get onto them?” becomes an architecture decision, and there are really only two answers underneath all the tools. Push: a central controller reaches out and applies changes to each machine. Pull: an agent living on each machine reaches out to a source and applies changes to itself. It sounds like a small implementation detail. It isn’t — it shapes how you scale, how you fight configuration drift, and what happens to the machine that was powered off when the change went out.

Push: the controller goes to the machines

In the push model, a control node holds the desired state and connects out to each managed machine — commonly over SSH — to apply it. Nothing special has to be installed on the targets beyond a way in. You run the tool, it fans out to the fleet, it makes the changes, it reports back.

The appeal is real:

  • No agent to install or maintain. If a machine has SSH and an interpreter, it’s manageable. Nothing extra to deploy, secure, or keep running on every node.
  • On-demand and ordered. You decide exactly when a change goes out, and you can orchestrate multi-machine sequences (“upgrade the database nodes one at a time, wait for each”) because a single brain is coordinating.
  • Easy to reason about. One controller, one run, one clear picture of what happened.

The costs show up as the fleet grows:

  • The controller needs to reach every machine. Network path, credentials, firewall — the push model assumes connectivity to each target, which gets harder across segments and NAT.
  • It scales with connections. Pushing to thousands of machines means thousands of connections from one place; it works, but you feel it, and it’s a burst not a steady state.
  • It’s a point in time, not continuous. A machine that’s down or unreachable during the run simply doesn’t get the change. Nothing corrects it until the next run.

Pull: the machine comes to the source

In the pull model, every machine runs an agent that periodically fetches the desired state from a central source and applies it to itself. The control plane publishes “here’s how you should be configured”; the fleet continuously reconciles toward it.

What that buys you:

  • It scales to huge fleets. Ten thousand agents pulling on their own schedule spread the load out; there’s no single node opening ten thousand connections. The work is distributed by design.
  • It’s continuous and self-healing. Agents re-apply on a cadence, so configuration drift — someone hand-edited a file, a package got downgraded — gets corrected automatically on the next cycle. The desired state is enforced, not just applied once.
  • It handles machines that come and go. A node that was offline pulls and converges as soon as it’s back. Ephemeral and autoscaled machines configure themselves on boot without a controller needing to know they exist.

And the costs:

  • Now you run an agent — and its infrastructure. Something has to be installed on every node, kept running, secured, and upgraded, plus the server it pulls from. That agent is privileged software you operate, same as any other.
  • Change is less immediate and less ordered. You publish the desired state and wait for agents to pick it up on their cycle; coordinating “these before those” across independent pullers is harder than a controller sequencing it.

The trade, in one line each

  • Push = simple, agentless, on-demand, precisely orderable — but the controller must reach everything, it scales with connections, and it misses whatever was unreachable at run time.
  • Pull = scales enormously, corrects drift continuously, handles ephemeral nodes — but you own an agent and its control plane, and changes propagate on a cadence rather than on command.

How to actually choose (and why “both” is common)

Ask what your fleet looks like and what hurts:

  • Small, stable, well-connected fleet where you want tight control and no agents? Push. It’s simpler and the downsides barely bite at small scale.
  • Large, dynamic, or drift-prone fleet where machines come and go? Pull. Continuous reconciliation and distributed load are exactly what you need, and the agent overhead pays for itself.

In practice a lot of shops run both: pull for the steady-state baseline that should always be true across the whole fleet, and push for the deliberate, orchestrated, “do this now, in this order” operations — the same reason a runtime toggle beats a redeploy for operational levers. And whichever you pick, the discipline of only acting when something actually changed applies — a pull agent re-applying every cycle absolutely should not bounce a service every cycle.

The reason it’s worth naming the two shapes is that most “our config management is painful” complaints are really a mismatch: a push tool strained across a fleet that wanted pull’s continuous reconciliation, or a pull system fighting someone who needed push’s precise orchestration. Match the shape to the fleet and the pain mostly goes away. If you’ve moved a fleet from one model to the other, I’d like to hear what pushed you.