Numba is great for pure functions on primitive types but it breaks down when you need to pass objects around. PyPy is fantastic for single-threaded applications but doesn't play nicely with multiprocessing or distributed computing IME. Numpy helps for stuff you can vectorize, but there's a lot of stuff you can't (or can but shouldn't); it also brings lots of minor inconveniences by virtue of not being a native type - e.g., the code to JSON serialize a `Union[Sequence[float], np.ndarray]` isn't exactly Pythonic.
It's easier to write Julia code than to deal with Numba tbh and the ecosystem around Julia makes the code composable which is often not the case if you write Numba code and have to deal with other libraries.
Composability, speed, static analysis, type system, abstractions, user defined compiler passes, metaprogramming, ffi, soon static compilation, differentiability and more create an effect that far exceeds numba