While Salt did great things to our deployment abilities (we didn't really have much prior to it) … it's not a tool I can recommend. It's design in comparable to PHP or MySQL, and I frankly believe someone should write the equivalent of "A Fractal of Bad Design" or "Do Not Pass This Way Again" for it.

1. Salt simply broadcasts commands out to the nodes connected to it. Because it has no concept of who should be connected to it, it cannot compute whether a node is missing, or if that missing node matters. It's test.ping command is just another command, too, so it suffers the same problems rendering it useless as a ping command

1. Salt's CLI will return success on failure.

1. It is not able to parallelize within a node.

It helps to know what a "state" looks like in Salt past here (this is YAML):

a_name: # the name of the state; the name/and mapping value here comprise the state
pkg.installed: # a state function; this installs a package
- arg1: value # args to the function. Yes, it's a list of single-element maps.
- arg2: value
user.present: # another state function
- …

These are effectively steps that salt will execute, typically in the order you define them, with some exceptions: a. you can specify dependencies b. you can specify that things run "first" or "last"

Also, note that this YAML file is templated with Jinja2.

1. You can't create and depend on a "PHONY" target; this means if you want to depend on the result of several states, you're SoL. You can just inline the set of states that you need, everywhere you need them, which is bad, or you can use a temporary file on disk, which is a hack.

1. Attempting to write code (which, really, is what SLS is) in YAML is crazy. (You can actually write these in at least 4 different languages! All Salt needs is a JSON-like structure.)

1. It is not able to pass information between "states" (a "state" in salt is a task in the grand list of stuff it needs to execute).

1. The error reporting leaves much to be desired. If you make a mistake in a YAML file, you can easily receive back errors with wrong line numbers, wrong file names, quoting the wrong part of the file.

1. At least when we used it, there was no way to properly escape inputs to the YAML file. (This might have been fixed; I honestly can't remember. At some point, it was "fixed", but not really, because the fix didn't work for any practical purpose.)

1. The minions would just "crash", and by crash, I mean, just stop responding. Since its not an outright crash

1. Bug reports were generally met with "you're not using the latest version, please upgrade"; generally, I'm understanding of this attitude, as it takes some work to determine if a bug being experienced in an old version is still present in a new version. Salt's architecture made upgrading nigh-impossible: minions/servers of different versions weren't compatible; DNS couldn't be used to switch minions over in some of our hair-brained ideas to gradually upgrade as the minions would cache DNS results indefinitely.

1. Minions would reconnect automatically; for whatever reason, reconnecting took a considerable toll on the server. If you hit the point where there were too many minions talking to the server, the fleet as a whole would go into a death spiral: too many minions attempting to connect causes an already connected one to miss a keepalive ping, and reconnect. Now you have yet another minion attempting to reconnect, and the problem is worse. More and more minions start doing this, and you're hosed. We had to restart the entire fleet of minions (by hand, b/c our manner of running a distributed command on the fleet was salt) multiple times.

1. Salt in some places, such as templating a file on a minion, needs to reference a file on the server. A relative path would have sufficed wonderfully, but instead Salt uses "salt: URLs". a. they're not URLs, and b. they MUST be absolute. This means that if you move a subtree of stuff (such as for refactoring), you're forced to adjust these URLs. Thankfully, they're easily greppable.