FiveM Server Optimization: Finding and Fixing Resource Bottlenecks

Published on | Updated

Performance optimization guide for FiveM servers. Covers resource profiling, client/server performance monitoring, entity management, and common bottlenecks.

FiveM server

A fresh FiveM server runs smooth. After adding 80 resources, it starts struggling. Finding which resources cause the problem, and fixing them, is the core skill of running a FiveM server.

Profiling Tools

Built-in Profiler

FiveM has a built-in profiler that shows where server time goes, per resource:

profiler record 500
profiler status
profiler view

The number is frames, not seconds. The Cfx.re docs suggest 500 frames as a starting point because it covers a useful stretch of activity. profiler status shows how far the capture is. On the server console, profiler view prints a link that you open in Chrome yourself; profiler saveJSON name.json keeps the capture so you can compare it with a later one.

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

  1. Enable resmon: Identify top resource consumers
  2. Profile server: Record a profile of about 500 frames during peak hours
  3. Rank by impact: Sort resources by tick time consumed
  4. Investigate top offenders: Read the code, find the bottleneck
  5. Fix or replace: Optimize the code or find an alternative resource
  6. Re-measure: Verify the fix actually improved performance

Target Metrics

Rough targets to aim for. These are a rule of thumb, not official Cfx.re limits:

  • Server tick time: Below 15ms average, lower is better
  • No single resource: Above 3ms per tick
  • Memory: Stable, not continuously growing
  • Client FPS: Above 30fps for players with mid-range hardware

A faster CPU core gives you more headroom, but it will not rescue a resource that burns several milliseconds every tick. The profiler finds that resource; hardware only buys time. On Space-Node FiveM hosting the hardware follows the region you pick: a Ryzen 9 9950X in Europe, a Ryzen 9 7950X3D in the USA, a Ryzen 9 5950X in Singapore and Australia, and Ryzen 9 3900X-class hardware in India.