When exactly does PlayerAdded fire?

For those searching this up in the year 2025 and now with deferred events:
I was wondering this as I was trying to work out some race conditions. I did some testing with a bunch of callbacks bound to various runservice events, as well as playeredadded event in the micro profiler. The events of a frame are shown in this diagram

The backend core server script handles new player connections in the Replication Receive phase. I don’t know why the diagram depicts this event having no hooks, when it definitely should have hooks. This Replication Receive phase is also when the backend core scripts receive remote event firings. Any callbacks bound to Replication Receive are scheduled to run at the next resumption point (because of deferred events), and that resumption point is the Run Legacy Scripts point, i.e. if a script just happened to be created at an earlier resumption point in the current frame, it’s execution would coincide with callbacks bound to Replication Receive.

The Replication Receive phase comes after the PreRender phase (formerly called RunService.RenderStepped) and execution of any of it’s bound callbacks. After Replication Receive you have some other resumption points of the PreAnimation PreSimulation (physics) and PostSimulation events, which probably aren’t too useful but heres a more useful ordering:

  1. Functions bound to render step (using RunService:BindToRenderStep)

  2. Functions bound to PreRender (formerly .RenderStepped)

  3. Functions bound to remote events and PlayerAdded event, + new scripts that are running for the first time

  4. Animation, then physics steps

  5. Threads that used task.wait() or were inside of task.delay() and had the waiting timer run out in the current frame

  6. Threads bound to Heartbeat


MORE INFO about PlayerRemoving:
This below has nothing to do with the original post! This is just extra info for the curious!

This got me thinking about PlayRemoving. Strangely, I thought that PlayerRemoving would also fire at the same point as Player Added, but it doesn’t. In fact, it doesn’t occur at any point in the task scheduler cycle diagram at all!
From looking at the microprofiler, the PlayerRemoving event seems to be happening before anything bound using BindToRenderStep. (The server technically doesn’t render anything but this step still exists). It looks like:
-Player leaves on frame 6
–At very beginning of frame 7, before anything else runs, the backend core server script on the main thread (core server script is something we don’t have access to, it just exists when server is created), will see if any players had left on the previous frame. If a player has left, it does some cleaning up (I’m assuming player instance is removed from the Players service at this point too), then fires any callbacks bound to the PlayerRemoving event. At this point, from the perspective of the server, the frame hasn’t even begun yet!

2 Likes