RenderStepped fires before a frame, Heartbeat fires during a frame.
It’s best to use these when you need extreme precision, ex: updating something in-line with the camera, a custom wait function, etc.
I wouldn’t recommend using these to completely replace wait() in a loop as running something every frame is inherently intensive, but using something like an aforementioned custom wait function with a default of 0.03 would be more reliable than flat out using wait()
RenderStepped is fired every render frame, Heartbeat runs after every physics update. Additionally, Stepped fires before a physics update. Custom wait solutions have been made using these events yes. I will go ahead and leave you this as to why people might go for a custom wait solution: