We do use Spec heavily, we use it to define our domain data model for all data which crosses the application boundary (data which we will persist to disk, database, or data which we send/receive from other services (over APIs), or data which we take from the user or return to the user.
What we've found happens to us, is that because Clojure is dynamically typed, we actually spend more time focusing on making sure we have well specified and properly designed our data model for data which enters/leaves the application boundary, and that we use runtime validation everytime the data is about to leave the app boundary or enter it from a non-trusted source.
When we used Java and Scala, we did not spend quite as much time here, because you've already got your internal types, and you kind of take them as your data model, and rely on them for validation and specification. The issue is the types only go so far to perform validation, and you've often designed them in terms of the implementation needs, and not the domain model. A dynamically typed language like Clojure teaches you to be extra careful with data to make sure you don't mess it up, and it gives you really powerful tools for it, such as Spec and the REPL.
This turns out to help I've found in an enterprise context, because even with a statically typed language, when data enters/leaves the boundary of the application it is no longer within the purview of the type checker.
So with Clojure, we end up spending way more time thinking through our domain model and validating it. Which worked pretty well for us.
You also need to learn how to properly design an app in Clojure, and it's very different than other languages, so it's possible to overcomplicate things and shoot yourself in the foot. But if you do it right, it makes for very simple code bases that are way smaller in LOC.
Generally, we have one module that specifies our data model for the bounded context of our app. Another module to construct, validate, convert, and manipulate entities from our data model. And then we have a main module with all our APIs, each API implementation lives in its own module. Shared logic exist in a shared module. And shared state exist in another shared module.
It takes a bit of a different mindset, like knowing to ski and then trying to learn to snowboard, but for me I ended up liking it much better, and the lack of static types didn't bother me, the strong functional immutable leaning of Clojure, along with the help of the interactive REPL development style makes up for it.