Packages are implemented as functions that take dependencies as arguments, do some stuff and ultimately output the result of calling mkDerivation (i.e. a derivation).
`override` allows you to change the arguments of the package, while `overrideAttrs` allows you to change the arguments of mkDerivation: the implementation of the package itself. `overrideDerivation` is essentially a deprecated `overrideAttrs` version.
https://nixos.org/manual/nixpkgs/stable/#chap-overrides for a better explenation.
`overrideAttrs` changes the arguments of the former, while `overrideDerivation` changes the arguments of the latter. The reason is it's "deprecated" is that it forces a full evaluation of `stdenv.mkDerivation` before it can continue and it override the lower-level derivation, so some niceties that Nixpkgs provides don't work with it.
Also some of the higher level constructs really aren't clear (like overrideDerivation/overrideAttrs/override, I still don't fully get). And mkDefault/mkForce/etc could be a bit more front and center rather than in "lib".
Also every time I run nixos-rebuild and it takes several+ seconds to evaluate my Nix expression I've got to wonder how much the implementation being this cute functional fixpoint is holding performance back.