To compile your namespace for uberjar (if you enabled AOT), the clojure compiler must load your namespace. This will always cause all the top level side effects.
The best way to handle this is to never have side effects in the top-level code (whether inside or outside the def form) and have initialization functions to implement any side effects you need to run.
A workaround might be to create a small namespace that uses introspection to load the rest of your code at runtime, but not at compile time — using this function:
(defn -main [] (require 'my.primary.ns) ((resolve 'my.primary.ns/start)))
if this namespace is compiled, jvm can find -main and run it, even though your other code does not compile. The require runtime will cause the clojure compiler to load the rest of your code only at runtime, and resolve will require -main to compile cleanly - it returns a reference to var, which then calls your function when called.
source share