A fresh FiveM server runs smooth. After adding 80 resources, it starts struggling. Finding which resources cause problems - and fixing them - is the core skill of FiveM server operation.
Profiling Tools
Built-in Profiler
FiveM has a built-in profiler that shows per-resource server tick time:
profiler record 25
profiler view
This records 25 seconds of activity and shows which resources consumed the most server time per tick.
resmon (Resource Monitor)
Enable the built-in resource monitor:
resmon 1
Opens a real-time display showing:
- CPU time per resource (server and client)
- Memory usage per resource
- Tick time contribution
Client-Side
Players can open resmon too (if enabled). Client-side performance matters for frame rate:
- Heavy NUI (HTML) interfaces
- Streaming assets (custom vehicles, maps)
- Client-side scripts running expensive logic every frame
Common Bottlenecks
1. Database Queries (Biggest Culprit)
Synchronous database calls block the server thread. One slow query stops everything for every player.
Symptoms: Periodic freezes, especially when players perform actions (opening inventory, checking bank)
Fix: Use async database libraries (oxmysql). Never use MySQL.Sync in production.
2. Server-Side Loops
Scripts running logic every tick (every 0ms) when they don't need to:
-- BAD: Checking every frame
Citizen.CreateThread(function()
while true do
CheckAllPlayerPositions() -- Runs 60+ times per second
Wait(0)
end
end)
-- GOOD: Check every second
Citizen.CreateThread(function()
while true do
CheckAllPlayerPositions()
Wait(1000) -- Runs once per second
end
end)
3. Entity Spawning
Creating entities without cleanup:
-- BAD: Vehicle spawns never cleaned up
function SpawnTestVehicle(model, coords)
local vehicle = CreateVehicle(model, coords.x, coords.y, coords.z, 0.0, true, true)
return vehicle
end
-- GOOD: Track and cleanup
local spawnedVehicles = {}
function SpawnTestVehicle(model, coords)
local vehicle = CreateVehicle(model, coords.x, coords.y, coords.z, 0.0, true, true)
table.insert(spawnedVehicles, vehicle)
return vehicle
end
function CleanupVehicles()
for _, vehicle in ipairs(spawnedVehicles) do
if DoesEntityExist(vehicle) then
DeleteEntity(vehicle)
end
end
spawnedVehicles = {}
end
4. Excessive Network Events
Every TriggerClientEvent and TriggerServerEvent uses bandwidth and processing:
-- BAD: Broadcasting to all players every second
Citizen.CreateThread(function()
while true do
TriggerClientEvent("updateHUD", -1, GetAllPlayerData())
Wait(1000)
end
end)
-- GOOD: Send only to relevant players, only changed data
function SendPlayerUpdate(playerId, data)
TriggerClientEvent("updateHUD", playerId, data)
end
5. Heavy NUI Interfaces
React/Vue/Angular interfaces that re-render constantly:
- Keep NUI iframes hidden when not in use
- Don't send data to NUI every frame
- Use efficient rendering (virtual lists for large data sets)
Optimization Workflow
- Enable resmon: Identify top resource consumers
- Profile server: Record 25-second profiles during peak hours
- Rank by impact: Sort resources by tick time consumed
- Investigate top offenders: Read the code, find the bottleneck
- Fix or replace: Optimize the code or find an alternative resource
- Re-measure: Verify the fix actually improved performance
Target Metrics
For a smooth FiveM server at 64+ players:
- Server tick time: Below 15ms average (target 8-10ms)
- No single resource: Above 3ms per tick
- Memory: Stable, not continuously growing
- Client FPS: Above 30fps for players with mid-range hardware
On Space-Node, the Ryzen 9 7950X3D provides the single-thread performance that makes the difference between a 15ms and 8ms average tick time. That margin is what separates a server that feels responsive from one that feels sluggish.
