Back to Blog
Performance 14 min read March 5, 2026

How to Fix High Resmon in FiveM: Complete Optimization Guide (2026)

Learn how to read the resmon panel, identify resource-hungry scripts, and reduce server-side and client-side tick times. Practical techniques used by production servers with 200+ players.

fivem resmon fivem performance fivem optimization server lag fivem scripts

What Is Resmon and Why It Matters

Resmon (short for resource monitor) is FiveM's built-in profiling tool. It measures how much CPU time each running resource consumes per server tick. Open it in-game by typing resmon 1 in the F8 console.

Every script on your server gets a slice of the tick budget. The server runs at roughly 64 ticks per second, which means each tick is about 15.6 ms. If your combined resource usage approaches or exceeds that budget, players experience rubber-banding, desync, and general lag.

In 2026, with servers running 150–300 players under OneSync Infinity, monitoring resmon is not optional — it is the single most important maintenance task a server owner can perform.


How to Read the Resmon Panel

When you enable resmon, you see a sorted list with columns:

ColumnMeaningGood Value
ResourceScript name
CPU (ms)Milliseconds per tick (client-side)< 0.05 ms
Server (ms)Milliseconds per tick (server-side)< 0.10 ms

Key rules of thumb:

  • Any resource using more than 0.20 ms on the client deserves investigation.
  • Any resource using more than 0.50 ms on the server is a problem.
  • Resources showing 0.00 ms when idle are well-optimized — this is the standard that Jobs Creator by Alone Studios targets.

Top 5 Causes of High Resmon

1. Citizen.Wait(0) in Tick Loops

This is the single most common performance killer. A Citizen.Wait(0) inside a CreateThread loop means the code runs every single frame — 60+ times per second:

-- BAD: runs every frame even when player is far away

CreateThread(function()

while true do

Citizen.Wait(0)

local coords = GetEntityCoords(PlayerPedId())

-- heavy logic here every frame

end

end)

Fix: Use distance-based throttling. Run the heavy logic only when the player is nearby:

-- GOOD: adaptive wait based on distance

CreateThread(function()

while true do

local sleep = 1000

local coords = GetEntityCoords(PlayerPedId())

local dist = #(coords - targetCoords)

if dist < 10.0 then

sleep = 0

-- heavy logic only when close

elseif dist < 50.0 then

sleep = 500

end

Citizen.Wait(sleep)

end

end)

2. Unoptimized Native Calls

Some GTA natives are expensive. Calling GetClosestPed, GetGamePool, or raycast natives every frame wastes significant CPU:

-- BAD: GetGamePool allocates a new table every call

CreateThread(function()

while true do

Citizen.Wait(0)

for _, veh in ipairs(GetGamePool('CVehicle')) do

-- check something

end

end

end)

Fix: Cache the result and refresh on a longer interval:

local cachedVehicles = {}

CreateThread(function()

while true do

cachedVehicles = GetGamePool('CVehicle')

Citizen.Wait(2000) -- refresh every 2 seconds

end

end)

3. Client-Side Threads with Heavy Drawing

DrawMarker, DrawText3D, and other rendering natives must run at Wait(0) to appear smooth, but you should only call them when the player can actually see them. Always wrap draw calls inside a distance check.

4. Memory Leaks from Event Handlers

Registering events inside loops — or registering the same event multiple times — creates memory leaks that gradually increase resmon over time. Use a single registration per event and track state with variables.

5. Synchronous Database Queries

Running MySQL.Sync.fetchAll (or any blocking DB call) on the server main thread halts the entire tick until the query returns. This is the most common cause of sudden server-wide lag spikes.

Fix: Always use async variants: MySQL.query, MySQL.Async.fetchAll, or exports.oxmysql:query_async. See our SQL optimization guide for details.


Step-by-Step Resmon Optimization

Follow this process for every script with high resmon:

  1. Enable resmon — Type resmon 1 in the F8 console
  2. Sort by CPU/Server time — Identify the top 5 offenders
  3. Read the source — Open the resource's client.lua or server.lua
  4. Find tick loops — Search for CreateThread and Citizen.Wait
  5. Check wait values — Any Wait(0) without a distance gate is suspect
  6. Add distance checks — Wrap expensive logic in proximity conditions
  7. Cache expensive calls — Store results of natives and refresh on intervals
  8. Test and compare — Check resmon before and after your changes

Real-World Example: 0.15 ms to 0.01 ms

A common job script had this structure in its client loop:

CreateThread(function()

while true do

Citizen.Wait(0)

local ped = PlayerPedId()

local coords = GetEntityCoords(ped)

for _, marker in ipairs(Config.Markers) do

local dist = #(coords - marker.pos)

if dist < 50.0 then

DrawMarker(marker.type, marker.pos.x, marker.pos.y, marker.pos.z, ...)

end

if dist < 2.0 then

ShowHelpNotification(marker.label)

end

end

end

end)

Resmon: 0.15 ms (with 30 markers configured).

After optimization — splitting into two threads (one for drawing at Wait(0) only when nearby, one for distance scanning at Wait(500)): resmon dropped to 0.01 ms when idle and 0.04 ms when near markers.

This is exactly the approach used by Jobs Creator, which maintains 0.00 ms idle resmon regardless of how many jobs and markers are configured.


Tools for Monitoring Performance

ToolPurposeHow to Use
resmon 1Per-resource CPU usageF8 console command
resmon 0Disable resmon overlayF8 console command
profilerDetailed frame profilingprofiler record 30 in F8
txAdminServer-side resource statsWeb panel → Performance
hitch warningsServer tick overrunsAppears in server console

Common Mistakes to Avoid

  • Removing Wait entirely — This freezes the game. Always include Citizen.Wait in any loop.
  • Using Wait(1) thinking it is better than Wait(0) — In practice, both run every frame. Use Wait(100) or higher for real throttling.
  • Blaming the framework — ESX and QBCore cores are well-optimized. High resmon almost always comes from third-party scripts, not the framework itself.
  • Optimizing the wrong resource — Always check resmon data first. Don't waste time on a script using 0.01 ms when another uses 0.50 ms.

Checklist: Is Your Server Optimized?

  • ⬜ All tick loops use distance-based Citizen.Wait values
  • ⬜ No GetGamePool calls running every frame
  • ⬜ DrawMarker calls are wrapped in proximity checks
  • ⬜ All database queries use async methods
  • ⬜ No duplicate event handler registrations
  • ⬜ Top 5 resmon scripts are each under 0.10 ms
  • ⬜ Server tick rate stays above 60 tps during peak hours
  • ⬜ All job-related logic is handled by an optimized system like Jobs Creator

Need Help?

Performance issues can be complex. Our Discord community has experienced server developers who can help diagnose specific problems. If you want a job system that sets the standard for resmon efficiency, check out Jobs Creator by Alone Studios — built from the ground up for zero-impact performance.

→ See Jobs Creator Performance Benchmarks

Ready to Transform Your Server?

FiveM Job Creator eliminates every problem discussed in this article. 0.00ms resmon. No-code configuration. ESX & QBCore native.

Get Job Creator on Tebex — €29.99