Nix is a purely functional package management system. This means that the act of building a package does not have side effects, such as destructively updating or deleting files that may be used by other packages. Nix makes it easy for systems to use multiple versions of the same package simultaneously, and ensure that updating or removing a package can't break other packages. Furthermore, these actions are atomic, and so the system can't be left in an unstable state. This all means that behavior with Nix is very predictable, which is particularly useful in testing configurations and deploying across multiple systems.
Con Does not work well for services on non-NixOS systems
When using Nix with anything other than NixOS you can run into difficulties with trying to start up services. For example, you can install docker with Nix, but it won't integrate with the host system's systemd leaving you to handcraft awkward workarounds in order to start the background service that docker requires. This seems like a critical flaw when using Nix on anything that is not NixOS, and it's unfortunate because this affects many of the packages many users would be most interested in using Nix to handle.
Con Cannot handle filetypes that have different semantics across different versions
While the functional approach that Nix takes is great for sandboxing binary artifacts of packages, it seriously lacks any power in handling configuration files or user data. It's difficult to upgrade and downgrade files where semantics and syntax can change between versions. Especially in Debian/Ubuntu it can cause severe problems where the upgrade process blocks and the user needs to resolve the 3-way merge.