Puppet
Puppet manages configuration through a declarative language describing desired state. Agents on managed hosts check in with a Puppet server, receive a compiled catalogue, and converge the machine toward it. The default interval is thirty minutes.
Declarative, and what that actually buys
You declare that a package is installed, a service is running, and a file has certain content. Puppet determines what to change. This is genuinely different from a procedural script, which describes steps and must handle every starting state itself.
Because resources are declared rather than sequenced, Puppet builds a dependency graph and orders operations from stated relationships — a service requires its config file, which requires its package. This catches circular dependencies at compile time rather than at 3 a.m., and it is the technically strongest thing about the tool.
The corresponding cost is that the language is a language. Puppet’s DSL has its own syntax and idioms, and it is a real thing to learn, unlike Ansible’s YAML. That learning cost is most of why Ansible wins adoption arguments.
Pull, and continuous convergence
Agents check in on their own, so drift is corrected automatically. A manual change to a managed file is reverted at the next run without anyone noticing it happened.
For a large fleet where the goal is that every host matches its declared role, this is the right model and Ansible’s push approach is not. It is also occasionally infuriating in exactly the same way — an emergency manual fix silently reverted half an hour later is a memorable experience, and the correct response is to change the manifest rather than to fight the agent.
The cost of pull is infrastructure: a Puppet server, certificate management for agent authentication, and an agent on every host. That is a project before any value arrives, which is precisely the bootstrapping barrier Ansible avoids.
What it suits
Puppet suits large, long-lived, relatively homogeneous fleets where configuration correctness matters continuously and the operational investment is justified. It suits small or fast-changing environments poorly.
Its weakness is orchestration — sequencing actions across multiple hosts in a defined order. The model is per-host convergence, and coordinated multi-host operations are awkward. Ansible and Salt are both better there, and using Puppet for state with Ansible for orchestration is a common and reasonable combination.
See also: Ansible, Chef, SaltStack, and the comparison.