The actual dispatch happens at runtime, but the cool thing is that it verifies that multimethods cannot overlap, and it does this verification at compile-time (specifically at macro-expand-time)
As complex as Racket is (especially its macro system), this is a good example of how that complexity can sometimes enable very cool things as a library (like compile-time verification of non-overlapping multimethods)