Not an OCaml expert either but that looks tail recursive, you’re never going to blow the stack.
You can tell by how after the recursive call within aux, its result does not get used within the function. That means that the compiler doesn’t need to push a return address to the stack as the only code that would be at that address is instructions to pop another address and return there, we can short-circuit all that and jump from the base case (0) directly to where aux(10000) is supposed to return to instead of taking 10000 dumb steps (like practically all procedural languages do because they don’t have tail call optimisation).
This would’ve been different if you had concatenated the string not as an argument to aux.