The Complete Guide to FiveM Script Optimization & Low Resmon Performance (2026)
# The Complete Guide to FiveM Script Optimization & Low Resmon Performance (2026)
FiveM server owners and developers often face a common bottleneck: **client-side lag, high CPU tick times (Resmon), and frame drops** caused by unoptimized scripts. As roleplay servers scale beyond 100+ concurrent players, script efficiency becomes the difference between a smooth 60+ FPS experience and unbearable server stutter.
At **Code X Art Studios**, we build custom FiveM scripts optimized to run at **0.00ms to 0.01ms** tick times. In this comprehensive guide, we share proven engineering principles to optimize your FiveM Lua codebase for maximum server performance. ## 1. Eliminate Heavy Loops Inside `Citizen.CreateThread`
The most frequent performance drain in FiveM scripts is placing unconditioned `Wait(0)` loops inside client scripts. When a thread runs every single frame without distance checks, CPU usage scales exponentially with player count.
Bad Practice: Running Every Frame Unnecessarily ```lua -- BAD: Runs every frame regardless of distance Citizen.CreateThread(function() while true do Citizen.Wait(0) local playerPed = PlayerPedId() local coords = GetEntityCoords(playerPed)
if #(coords - vector3(100.0, 200.0, 10.0)) < 2.0 then DrawText3D(100.0, 200.0, 10.0, "Press [E] to interact") end end end) ```
Optimized Practice: Dynamic Wait Interval ```lua -- GOOD: Adapts tick rate dynamically based on player proximity Citizen.CreateThread(function() while true do local sleep = 1000 local playerPed = PlayerPedId() local coords = GetEntityCoords(playerPed) local dist = #(coords - vector3(100.0, 200.0, 10.0))
if dist < 10.0 then sleep = 0 if dist < 2.0 then DrawText3D(100.0, 200.0, 10.0, "Press [E] to interact") if IsControlJustReleased(0, 38) then -- E key TriggerServerEvent("myScript:interact") end end end
Citizen.Wait(sleep) end end) ``` ## 2. Leverage Event-Driven Architecture Over Poll Loops
Instead of constantly checking if a player is dead, inside a vehicle, or opening an inventory in a continuous loop, utilize state-based events. Major frameworks like QBCore and ESX export state variables and triggers.
- **Use State Bags**: `LocalPlayer.state.isLoggedIn` or `Player(source).state.inventoryOpen` allow checking states instantly without polling threads. - **Listen to Events**: Bind triggers to state-change events such as `gameEventTriggered` for entity deaths rather than constantly querying health states in a thread. ## 3. Optimize MySQL Database Queries (oxmysql)
Database lag translates directly to server-side tick time spikes. Blocking calls or excessive nested queries inside `oxmysql` freeze the server thread.
- **Always use Async Methods**: Never use blocking SQL calls inside critical gameplay events. Prefer `MySQL.prepare` or `MySQL.query` over synchronous alternatives. - **Batch Queries**: Use transactions when inserting multiple rows to avoid opening database connections repeatedly. - **Index Your Columns**: Ensure columns frequently queried (e.g., `citizenid`, `identifier`, `plate`) have database indexes set.
Looking for customized optimization services or custom script systems? Visit our [FiveM Catalog](/products) to learn more.
