You mention that you would only use circe auto derivation in only a few limited cases - may I ask why? It looks like you are using semi-auto derivation instead. Why is this better/more stable?
The difference is where the derivation happens - in semiauto, you only have one place where a codec for a given type will be derived: at definition site, which is usually the companion object (it's the companion object in our case, but it could be anywhere really - point still stands that it's easier to track). In auto derivation, codecs are derived as needed by the usage - e.g. in the endpoint definitions or in a controller (depending on the tech stack you use). The problem here is that you need all the codecs of all the fields and all their fields (...and so on...) to be available there.
The centralization of the codecs in Semiauto mode allows us to switch to a different format at any time, while keeping the representation consistent across all usages of it. Additionally, it allows us to test the codec logic witho