Evergreen practical guide. Official references checked on 16 September 2026. AI-assisted FiveMCoach editorial content. This article concerns Lua client scheduling, not a measured optimization of your resource.
What does Wait actually change?
Citizen.Wait yields the current coroutine. Zero resumes on the next game tick; a positive value specifies an approximate delay in milliseconds. Client ticks depend on frames, so a wait is not an exact timer. Cfx.re recommends zero for work required every frame.
Run yielding code in an appropriate coroutine, such as the handler created by Citizen.CreateThread. A new thread does not make a busy infinite loop harmless: the documented warning is that a loop without a yield can freeze the game. Check every branch, including error and early-return paths.
How do you decide whether a loop can wait longer?
Write one sentence describing the observable requirement before touching the delay. For example: “This display must remain visible while the mode is active,” or “This diagnostic note may update once a second.” These are proposed requirements, not claims about a particular native function. Check the documentation of the native you actually call.
Next, list what the loop does: presentation, state lookup, expensive calculation, or a business action. If these jobs have different timing needs, review them separately. Do not make an entire mixed loop slower simply because its least urgent calculation can wait.
Agree on a maximum acceptable reaction delay for periodic behavior. This is a product decision to test, not a universal FiveM setting. Write the acceptance case before implementation so a smoother performance graph cannot hide a missed interaction.
Can you try a small example without changing gameplay?
On a local development server, create a separate resource named wait_probe. Its resource manifest loads only one client script. This sample has no network events, database writes, rewards or player-state changes.
Create fxmanifest.lua:
fx_version 'cerulean'
game 'gta5'
client_script 'client.lua'
Create client.lua:
CreateThread(function()
for sample = 1, 3 do
Wait(1000)
print(("[wait_probe] sample %d of 3"):format(sample))
end
end)
Use the server console to run refresh, then ensure wait_probe, and inspect the client F8 console. The intended result is three numbered messages followed by no further sample output. The loop is deliberately bounded so it does not create a permanent logging task. See the resource command guide if the resource is not discovered.
If nothing appears, confirm the folder, manifest filename and client.lua spelling, then inspect startup errors before editing the delay. After the exercise, stop the resource with stop wait_probe. Do not add it to your production startup configuration.
Example verification: the files and control flow were reviewed against the documentation. The example was not executed inside FiveM, and no timing or performance result is claimed. Use it as a development exercise, not a benchmark.
How should you review a real timing change?
Keep the original version available. Test the inactive state, entry into the active state, normal use, exit and re-entry. Repeat at more than one client frame rate where practical. Record the actual behavior rather than only whether the console stayed quiet.
When profiling is relevant, Cfx.re documents profiler record 500, profiler status and profiler view. Capture the same scenario before and after your change and inspect the relevant thread. The profiler guide explains how captures expose resource and script work; it does not promise that changing a wait fixes that work.
Stop the rollout if the changed version misses the agreed behavior. Restore the previous implementation and isolate the job that can safely run less often. For broader diagnosis, use the FiveM performance playbook; for a structured foundation, explore the Lua curriculum.
