removeNode vs detach vs destroy?

This is not quite true. removeNode() does not clean up any memory. In fact, removeNode() and detachNode() are almost identical.
detachNode() removes the node from the parent’s list of children, meaning, the node will be detached from the scene graph. The extra thing that removeNode does is that it makes the NodePath no longer point to that specific node (node() will return None after a call to removeNode()), thus essentially reducing the reference count of the node by one.

Functionally, removeNode is almost equivalent to this:

nodePath.detachNode()
nodePath = None

Only when the reference count of the underlying node reaches zero will the node be destroyed from memory, which is when there are no more references to it left, be it by its parent, your NodePath or by some other reference you hold to it.