ZooKeeper's defaults get you a working ensemble quickly, then hand you a set of cliff-edges that most teams only discover during an incident.
The defaults work. Until the transaction log shares a disk with snapshots, an fsync stalls, and the log warns that it took Nms which will adversely affect operation latency. Until the data tree quietly grows for months, the heap fills, and every node throws java.lang.OutOfMemoryError: Java heap space at the same moment because they all hold the same tree. Until a GC pause trips ZooKeeper's own monitor with Detected pause in JVM or host machine (eg GC), clients miss heartbeats, and sessions expire — deleting the ephemeral nodes that Kafka, HBase, and HDFS depend on. Until a security-group change blocks the election port and the ensemble cannot elect a leader. Until a container fleet behind one IP hits Too many connections from /IP - max is 60 and new clients are refused.
These guides are written for engineers who already run ZooKeeper, not for people learning what a znode is. The goal is the mental model of how the ensemble actually behaves under load, the failure patterns that keep recurring, the monitoring story that catches them before they page anyone, and the runbooks you wish someone had handed you before your last incident.