Most FiveM performance problems are not caused by one terrible script. They are caused by forty reasonable ones, each doing a little bit of work every frame, added one at a time over months until the server feels sluggish and nobody can say why.
The fix is to treat performance like money: set a budget, measure what each resource spends, and make every new script justify its cost before it goes live. This post covers how to do that with the tools FiveM already gives you.
Why a budget, not a target
You will see people online quote "good" resmon numbers for individual scripts. Those numbers are useful as a rough sanity check, but they miss the point. What your players feel is the total: the sum of every client-side resource running in the same frame, on their hardware, in the part of the map they are standing in.
At 60 FPS a frame lasts about 16.7 ms. The game itself uses most of that. Your scripts share whatever is left with each other. On a lower-end PC, or a player recording and streaming at the same time, the margin is smaller still.
So the useful question is not "is this script fast?" but "what is this script costing, and is it worth it?"
Step 1: measure a clean baseline
Before you can budget, you need to know where you stand.
- Start your test server with only the framework and core libraries.
- Join, wait for everything to load, and open the F8 console.
- Run
resmon 1to open the resource monitor. - Stand still in a quiet area for a minute, then in a busy area for a minute.
Write down the CPU time for each resource in both places. This is your baseline. Everything you add later is measured against it.
Then add your gameplay scripts back in groups (jobs, then UI, then vehicles, and so on) and repeat. You will quickly see which group, and then which resource, is responsible for most of the cost.
Step 2: separate idle cost from active cost
There are two kinds of cost, and they need different fixes.
Idle cost is what a resource spends while the player is not using it. A garage script running a distance check every frame, even when you are on the other side of the map, is idle cost. This is the expensive kind, because every player pays it all the time.
Active cost is what a resource spends while it is being used: an open phone, a minigame, a menu. Some active cost is unavoidable and fine, as long as it drops back down when the player is done.
When you read resmon, look first at resources that sit above zero while nothing is happening. They are your biggest wins.
Step 3: know the usual suspects
After profiling a few servers, you start to see the same patterns again and again.
Tight loops with Wait(0)
CreateThread(function()
while true do
Wait(0)
local coords = GetEntityCoords(PlayerPedId())
if #(coords - shopCoords) < 2.0 then
DrawText3D(shopCoords, "[E] Open shop")
end
end
end)
This runs every single frame, everywhere on the map, for every player. The usual fix is to sleep longer when the player is far away and only tighten the loop when they are close:
CreateThread(function()
while true do
local sleep = 1000
local coords = GetEntityCoords(PlayerPedId())
local dist = #(coords - shopCoords)
if dist < 20.0 then
sleep = 0
if dist < 2.0 then
DrawText3D(shopCoords, "[E] Open shop")
end
end
Wait(sleep)
end
end)
Better still, use a zone or points library that handles enter/exit events for you, so the script does nothing at all until the player is nearby.
Many scripts doing the same distance checks
If ten scripts each loop over their own list of locations, you are paying for ten loops. Consolidating interaction points into a shared targeting or zones system usually cuts idle cost significantly.
UI that never sleeps
NUI pages that animate constantly, poll the game for data every frame, or keep hidden elements rendering can show up as high cost. Push data to the UI when it changes instead of polling, and make sure hidden UI is actually idle.
Server events fired too often
Client scripts that trigger server events every tick (for example, to sync a value that rarely changes) add network and server load. State bags or event-on-change patterns are usually a better fit.
Database calls in loops
On the server side, a query inside a loop, or a query on every player tick, will eventually hurt. Cache what you can, batch writes, and use the server profiler to find hot spots.
Step 4: use the server profiler too
Resmon shows client-side cost. Server-side, FiveM includes a built-in profiler that you can start from the server console, record for a period while players are active, and then inspect. Run it during a busy evening on your test server or a quiet period on live, and look for resources that dominate the server thread.
A server that hitches every few seconds often has one resource doing heavy work on a timer, such as a big save routine or a large query. The profiler makes that visible.
Step 5: write the budget down
Once you have a baseline, set rules for your team. For example:
- Idle resources should sit at or near zero. Anything that does not, needs a reason.
- Each new script is tested on the staging server first, with resmon screenshots in both a quiet and a busy area.
- Every script has an owner who is responsible for updating it and knows why it is there.
- One system per job. One inventory, one target system, one notification system. Duplicates cost performance and cause conflicts.
Keep the numbers from each test in a simple spreadsheet. When performance drops after an update, you will know exactly what changed.
Step 6: evaluate scripts before you buy them
Budgeting is easier if you avoid expensive scripts in the first place. Before adding anything new, whether free or paid:
- Ask for resmon readings from the developer, idle and in use, and then check them yourself on your own server.
-
Prefer scripts you can read. If you can open the client files, you can spot
Wait(0)loops and per-frame natives in minutes. - Check which libraries it depends on. A script that pulls in a second UI framework or a duplicate target system adds hidden cost.
- Look at how it handles distance. Does it use zones and sleep when the player is far away, or does it check everything every frame?
When you compare fivem server scripts from different sellers, framework support and features are only half the picture. The other half is whether the code respects your frame budget.
A simple monthly routine
- Pull the latest version of everything onto staging.
- Run the same resmon walk-through you used for the baseline.
- Run the server profiler during a busy session.
- Compare against last month's numbers.
- Fix, replace or remove the worst offender.
Removing one bad script each month does more for your players than any amount of tuning elsewhere.
Final thoughts
Performance is not something you fix once. It drifts every time you add, update or configure a resource. A written budget, a baseline and a short routine turn it from a crisis into a habit.
At xFiveM Shop that is how we think about scripts too: the ones that last on a server are those that do their job quietly and get out of the way. If you have a profiling trick or a resmon horror story, share it in the comments.
Top comments (0)