Skip to main content
TRACK A·SECURE AND LAUNCH·Verified June 2026 · Lua 5.4 · ox_lib 3.x
Learning with an AI assistant?
Copies this lesson plus 2026 ground rules (no lua54 'yes', Cfx.re Portal, correct callback signatures) as a ready-to-paste mentor prompt.
Module A2 · Operate and ship

The connection flow: deferrals, queue, and whitelist

Every player who joins your server passes through one server-side gate before they load a single thing. That gate is the playerConnecting event. The platform hands you an object called deferrals that lets you pause the join, show the player a message, then decide: let them in, or send them away with a reason. To defer a join is to hold it open while you make that decision. This is the only place you can stop a join. By the end you will have a working resource that holds a connection, checks a license against an allowlist, and rejects anyone who is not on it.

You'll build
A server resource that holds a connecting player, shows a loading message, checks a hardcoded license allowlist, and either lets them in or rejects them with a reason.
Time
~24 minutes
You need
Your qu_first_line_of_lua mental model, a local FiveM server you can restart, and the ability to read txAdmin Live Console.
You'll learn
The playerConnecting handshake -> the deferrals object (defer, update, presentCard, done) -> reading a player's license identifier server side -> gating entry with a server-authoritative allowlist
BEFORE YOU START

The handshake before the player loads

When someone clicks Connect, the server fires a playerConnecting event before the player has a ped, a server slot, or any resource loaded on their screen. This is the handshake window. It runs entirely on the server. It is the one moment where you hold all the control and the player holds none.

The platform passes your handler three things. The connecting player's name. A setKickReason function you can mostly ignore in favor of deferrals. And a deferrals object. That last one is the whole point of this lesson.

Calling deferrals.defer() tells the server "do not finish this join yet, I am going to take my time and decide." Until you call deferrals.done(), the player sits on the connecting screen and waits for you.

Why does this matter so much? Because this is the only place you can block a join. Once a player is fully connected, they already have a slot and their client is loading resources. Kicking them then is a cleanup, not a gate. Blocking them here, during playerConnecting, means they never get in at all.

And because the check runs on the server, the player cannot fake their way past it. The client may request a connection, but only the server grants it. That is what server-authoritative means: the decision lives on the machine the player does not control.

Keep reading the full lesson

Sign in to start, then unlock every step of this lesson and the full FiveM School with a membership.

Still ahead in this lesson
  • Build it
  • How it works
  • Common mistakes
  • What you can do now
  • Try it yourself

The remainder of The connection flow: deferrals and queue is available to FiveM School members.