← Back to blog
fivemoptimizationguideserver-cfg

The Complete FiveM Server Optimization Guide for 2026

By Limax ·

I’ve optimized dozens of FiveM servers over the past few years, from small 32-slot RP communities to 200-player servers. This guide covers everything I’ve learned — the stuff that actually moves the needle.

Server.cfg Settings That Actually Matter

OneSync

If you’re not running OneSync, stop reading and go enable it right now.

set onesync on

Without it, you’re capped at 32 players and entity synchronization is significantly worse. There’s no reason not to use it in 2026.

Game Build

Lock your game build so every player is on the same version. This prevents weird desync issues caused by different game versions having different behaviors.

sv_enforceGameBuild 3258

Use the latest build that’s stable for your setup.

Rate Limiters

State bag abuse is a real thing. Without rate limiters, a single bad client can spam state changes and lag your entire server.

set rateLimiter_stateBagFlood 150

Connection Queue

If you’re running a popular server, set up a proper connection queue to prevent join floods:

sv_maxclients 128
set sv_endpointprivacy true

Script Optimization Basics

The GetDistanceBetweenCoords Problem

This native is slow. Like, really slow compared to the alternative. Every time you call it, you’re making a native call across the Lua-C bridge.

-- Slow (native call)
local dist = GetDistanceBetweenCoords(x1, y1, z1, x2, y2, z2, true)

-- Fast (pure Lua math)
local dist = #(vector3(x1, y1, z1) - vector3(x2, y2, z2))

The vector math version is significantly faster because it stays in Lua. If you have scripts checking distances every frame (which you shouldn’t, but we’ll get to that), this adds up fast.

Cache Your Natives

Calling PlayerPedId() every frame is wasteful. The player’s ped doesn’t change that often.

-- Bad: calling native every frame
while true do
    Wait(0)
    local ped = PlayerPedId()
    -- do stuff with ped
end

-- Better: cache it and refresh periodically
local myPed = PlayerPedId()
CreateThread(function()
    while true do
        myPed = PlayerPedId()
        Wait(1000)
    end
end)

DrawMarker Distance Checks

This one drives me crazy. I see it in probably 70% of scripts I audit. A DrawMarker call running every frame with no distance check means the client is rendering a marker that might be 2 kilometers away and completely invisible.

-- Bad: rendering marker from across the map
while true do
    Wait(0)
    DrawMarker(1, x, y, z, ...)
end

-- Good: only render when close
while true do
    local dist = #(GetEntityCoords(myPed) - vector3(x, y, z))
    if dist < 30.0 then
        Wait(0)
        DrawMarker(1, x, y, z, ...)
    else
        Wait(2000)
    end
end

Entity Management

Clean Up After Yourself

The number one rule of entity management: if you create it, delete it. Every CreateVehicle, CreatePed, and CreateObject should have a corresponding DeleteEntity or SetEntityAsNoLongerNeeded.

Server-Side Entity Limits

You can control the maximum number of entities per type:

set onesync_entityLockdown strict

This prevents clients from creating unauthorized entities — a common exploit vector.

Vehicle Cleanup Scripts

Run a vehicle cleanup that periodically removes abandoned vehicles. Not the kind that deletes everything every 5 minutes (your players will hate you), but one that intelligently removes vehicles with no recent driver that are far from any player.

Database Optimization

Indexes Matter

If your queries are slow, chances are you’re missing an index. The most common one I see:

-- If you're looking up players by identifier frequently
CREATE INDEX idx_users_identifier ON users(identifier);

Connection Pooling

oxmysql handles this for you, but if you’re using raw mysql-async, make sure you’re not creating a new connection for every query.

Query Optimization

Avoid SELECT * when you only need one column. Avoid running queries inside loops. Batch operations where possible.

Monitoring Is Not Optional

You wouldn’t run a web application without monitoring. Your FiveM server deserves the same treatment.

The problem with resmon is that it’s a snapshot. You see the current state but not the trend. You can’t tell if that 0.15ms resource has been slowly climbing over the past week, or if hitches spike every evening when player count peaks.

FivePulse tracks everything over time — health scores, per-resource CPU usage, entity counts, hitches, player count. When something goes wrong, you can look at the timeline and see exactly when it started and what changed.

Quick Wins Checklist

If you’re looking for the fastest improvements:

  1. Search all client scripts for Wait(0) and add distance-based adaptive waits
  2. Replace GetDistanceBetweenCoords with vector math
  3. Switch any MySQL.Sync calls to async
  4. Remove unused resources
  5. Add entity cleanup for abandoned vehicles
  6. Enable OneSync if you haven’t
  7. Set rate limiters in server.cfg

Do those seven things and you’ll see a noticeable improvement. For everything else, let FivePulse scan your server — it catches things humans miss.

Want to find your server's problems automatically?

FivePulse scans your server and tells you exactly what's wrong — with copy-paste fixes.

Try FivePulse Free