All posts

Reading resmon: what a slow FiveM server is actually telling you

2 min readLegacy Scripts

"The server is lagging" is the least useful bug report in FiveM, because it covers at least four unrelated problems. Here is how to work out which one you have.

First, separate the three kinds of lag

Client FPS — the player's own frame rate. Caused by their hardware, their graphics settings, or a client-side script doing too much work every frame.

Server tick — the server struggling to keep up. Everyone feels this at once, usually as rubber-banding and delayed events.

Network — packet loss or latency between player and server. Feels like lag, is not fixed by any script change.

Ask one question to tell them apart: is it everyone at the same time, or one person? Everyone at once points at the server or the network. One person points at their client.

Using resmon

In the client console (F8), run:

resmon 1

You get a live table of every running resource with its CPU time in milliseconds. This measures client-side cost, on that player's machine.

Rough guidance for a resource at idle:

  • Under 0.05ms — fine, ignore it.
  • 0.05–0.5ms — normal for something actively doing work, like a HUD.
  • Over 1.0ms sustained — worth investigating.
  • Over 5.0ms — this is your problem.

The number that matters is the one at idle, when you are standing still doing nothing. A script that spikes to 3ms while you are using its menu is fine. A script sitting at 3ms while you stand in a field is not.

The usual culprit

Most runaway client cost comes down to one pattern — a loop with no wait:

CreateThread(function()
    while true do
        Wait(0)              -- runs every single frame
        -- distance checks, marker drawing, whatever
    end
end)

Wait(0) means "run again next frame", roughly 60 times a second, forever. Done for drawing a marker the player is standing on, that is correct. Done for checking whether the player is near any of 200 locations, it is burning frames.

The fix is to slow the loop down when nothing is happening:

CreateThread(function()
    while true do
        local sleep = 1000               -- idle: check once a second
        if isPlayerNearAnything() then
            sleep = 0                    -- close by: run every frame
        end
        Wait(sleep)
    end
end)

Same behaviour to the player, a fraction of the cost.

Server side

resmon does not show server cost. For that, use the server console:

profiler record 500
profiler view

That records 500 frames and opens a viewer. What you are looking for is anything doing database work inside a frequent loop — a query that runs per player per second will find the ceiling of your server long before your player count does.

What to do about a script you did not write

If a paid resource is sitting at 5ms idle, tell whoever sold it to you. That is a defect, and any developer worth buying from will want to know. Include your resmon reading, the resource version, and what you were doing at the time — that is a bug report someone can act on.

We publish resmon figures for our own scripts on their product pages, and we treat a regression in them as a bug. If you catch one of ours misbehaving, tell us in Discord and we will fix it.