Server performance is the single biggest factor in player retention. No amount of amazing scripts, beautiful MLOs, or compelling roleplay rules will save your server if players experience constant lag, desync, and crashes. Conversely, a smooth-running server with fewer features will always outperform a lag-ridden server that has everything.
This guide is comprehensive. We'll cover every aspect of FiveM server optimization — from the Lua scripts running on your server to the hardware underneath it. Whether you're troubleshooting existing performance issues or optimizing a new server before launch, this guide has you covered.
Understanding FiveM Performance
Before optimizing anything, you need to understand where performance bottlenecks actually occur. FiveM servers have three distinct performance domains:
1. Server-side performance
This is your server's CPU handling Lua/JavaScript execution, database queries, and network synchronization. When this struggles, all players experience lag simultaneously.
2. Client-side performance
This is each player's computer rendering the game world, including custom assets like vehicles, MLOs, and NUI interfaces. When this struggles, individual players experience FPS drops.
3. Network performance
The data flowing between server and clients. OneSync handles entity synchronization, and your scripts handle custom data sync. When this struggles, players experience desync — seeing different things than other players.
Optimizing only one domain won't fix problems in the others. You need to address all three.
Step 1: Measure Before You Optimize
The first rule of optimization: measure, don't guess. FiveM provides built-in tools to identify exactly what's causing problems.
resmon (Resource Monitor)
This is your most important diagnostic tool. Run it in your server console:
resmon 1 -- Enable resource monitor
resmon 0 -- Disable it when done
This shows CPU time consumed by each resource. Sort by the highest values and you'll immediately see your biggest offenders. Healthy values:
| Resource state | Acceptable CPU time | Concerning | Critical |
|---|---|---|---|
| Idle (no players nearby) | < 0.02ms | 0.05-0.1ms | > 0.1ms |
| Active use | < 0.2ms | 0.2-0.5ms | > 0.5ms |
| Heavy operation (brief spike) | < 1ms | 1-3ms | > 3ms |
txAdmin performance panel
txAdmin's dashboard shows server FPS (tick rate), player count, and memory usage over time. A healthy server maintains a consistent 64 tick rate (displayed as server FPS). If it drops below 30, players will notice lag.
Step 2: Script Optimization
Scripts are the most common performance bottleneck on FiveM servers. Here's how to fix them:
The Wait(0) problem
This is by far the most common performance killer in FiveM scripts. Wait(0) means "run this code every single frame" — that's 60+ times per second. Most operations don't need to run that frequently.
-- TERRIBLE: Checks distance every frame for every player
Citizen.CreateThread(function()
while true do
Wait(0)
local playerCoords = GetEntityCoords(PlayerPedId())
local distance = #(playerCoords - targetCoords)
if distance < 2.0 then
ShowInteractionPrompt()
end
end
end)
-- MUCH BETTER: Two-stage approach
Citizen.CreateThread(function()
while true do
local playerCoords = GetEntityCoords(PlayerPedId())
local distance = #(playerCoords - targetCoords)
if distance < 50.0 then
-- Close enough to matter: check more frequently
Wait(0)
if distance < 2.0 then
ShowInteractionPrompt()
end
else
-- Far away: check infrequently
Wait(2000)
end
end
end)
This simple pattern — checking distance at a slow rate and only switching to frame-by-frame when needed — can reduce a script's CPU usage by 90% or more.
Minimize native calls
FiveM native functions (like GetEntityCoords, GetVehicleClass, etc.) have overhead. Calling them repeatedly in tight loops is wasteful:
-- BAD: Calls GetEntityCoords twice
local dist = #(GetEntityCoords(PlayerPedId()) - GetEntityCoords(targetPed))
local heading = GetEntityHeading(PlayerPedId())
-- BETTER: Cache the result
local myPed = PlayerPedId()
local myCoords = GetEntityCoords(myPed)
local dist = #(myCoords - GetEntityCoords(targetPed))
local heading = GetEntityHeading(myPed)
Use vectors properly
-- SLOW: Creating table and doing manual math
local dx = pos1.x - pos2.x
local dy = pos1.y - pos2.y
local dz = pos1.z - pos2.z
local dist = math.sqrt(dx*dx + dy*dy + dz*dz)
-- FAST: Built-in vector distance
local dist = #(pos1 - pos2)
Remove unused scripts
Every running resource consumes CPU time, even if idle. Audit your resources folder and remove or stop:
- Scripts you installed to test but never used
- Duplicate functionality (two HUDs, two phone systems)
- Debug and development tools left running in production
- Default FiveM resources you don't need (like
chatif you have a custom chat)
Step 3: Database Optimization
Slow database queries block the server's main thread, causing lag spikes that affect all players simultaneously. This is especially problematic during player joins and disconnects when multiple queries run at once.
Add proper indexes
Indexes are the single most impactful database optimization. Without them, every query scans the entire table:
-- Check which queries are slow
-- In MySQL/MariaDB, enable the slow query log:
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 0.5;
-- Add indexes to commonly queried columns
ALTER TABLE players ADD INDEX idx_citizenid (citizenid);
ALTER TABLE players ADD INDEX idx_license (license);
ALTER TABLE player_vehicles ADD INDEX idx_citizenid (citizenid);
ALTER TABLE phone_messages ADD INDEX idx_sender (sender);
ALTER TABLE phone_messages ADD INDEX idx_receiver (receiver);
Optimize oxmysql usage
-- BAD: Fetching all columns when you only need one
exports.oxmysql:execute('SELECT * FROM players WHERE citizenid = ?', {citizenid})
-- GOOD: Only fetch what you need
exports.oxmysql:execute('SELECT money, job FROM players WHERE citizenid = ?', {citizenid})
-- BAD: Multiple individual queries in a loop
for _, id in ipairs(playerIds) do
exports.oxmysql:execute('UPDATE players SET lastLogin = NOW() WHERE id = ?', {id})
end
-- GOOD: Batch update
exports.oxmysql:execute('UPDATE players SET lastLogin = NOW() WHERE id IN (?)', {table.concat(playerIds, ',')})
Database maintenance
- Clean old data: Delete old logs, expired bans, and orphaned records periodically
- Optimize tables: Run
OPTIMIZE TABLE tablenamemonthly on large tables - Monitor size: A database that's grown to several GB might have tables that need pruning
Step 4: Streaming and Asset Optimization
Custom vehicles
Vehicles are the most common cause of client-side FPS drops. Guidelines:
- Polygon count: Keep under 70,000 polygons per vehicle. Over 100k will cause noticeable FPS drops.
- Textures: Use 1024x1024 textures maximum. 2048x2048 is rarely justified for a game vehicle.
- LOD models: Every vehicle should have Level of Detail models that reduce polygon count at distance.
- Limit total vehicles: 50-80 custom vehicles is a reasonable limit. Beyond 100, you're asking for trouble.
- Test individually: Add vehicles one at a time and check the impact on FPS.
MLO interiors
- Prop count: Keep interior props under 500 per MLO
- Streaming distance: Set appropriate streaming distances so MLOs unload when far away
- Collision: Use simplified collision meshes, not full-detail models for collision
- Limit total MLOs: 10-15 MLOs is typical. Beyond 20, test thoroughly.
Step 5: Server Configuration
Recommended server.cfg settings
# OneSync (required for 32+ players)
set onesync on
# Distance culling — entities beyond this distance aren't synced
# Lower = better performance, but players can't see far
set onesync_distanceCulling true
set onesync_distanceCullVehicles true
# Game build — use latest for best stability
set sv_enforceGameBuild 2802
# Disable script hook (security + performance)
set sv_scriptHookAllowed 0
# Player slots — set this to your actual target, not maximum
sv_maxclients 64
# Network rate settings
# Don't change these unless you understand networking deeply
set sv_pureLevel 1
Scheduled restarts
FiveM servers accumulate memory usage and minor issues over time. Scheduled restarts every 6-12 hours help maintain consistent performance. txAdmin supports this natively through its scheduler.
Step 6: Hardware Recommendations
Your hardware determines the ceiling of your server's performance. No amount of software optimization can overcome inadequate hardware.
| Player count | CPU | RAM | Storage | Network |
|---|---|---|---|---|
| Up to 32 | 4 cores @ 3.5GHz+ | 8 GB | SSD 50GB | 100 Mbps |
| 33–64 | 6 cores @ 3.8GHz+ | 16 GB | NVMe 100GB | 250 Mbps |
| 65–128 | 8 cores @ 4.0GHz+ | 32 GB | NVMe 200GB | 500 Mbps |
| 129+ | 10+ cores @ 4.2GHz+ | 64 GB | NVMe 500GB | 1 Gbps |
CPU matters most. FiveM is primarily CPU-bound. Single-thread performance is more important than core count, but you need enough cores for the OS, database, and any other services running on the same machine.
Recommended hosting providers: OVH Game, Hetzner dedicated, Contabo VPS (budget option). Avoid shared hosting for anything above 32 players.
Step 7: Ongoing Monitoring
Optimization isn't a one-time task. Your server's performance will change as you add scripts, gain players, and modify configurations. Build a monitoring habit:
- Weekly: Run
resmonand check for any new high-CPU resources - After every script install: Check resmon before and after. If a new script adds more than 0.1ms, investigate.
- After updates: Framework and script updates can change performance characteristics
- During peak hours: Connect during your busiest times and check for issues players are experiencing
- Database size: Check monthly. Growing tables might need cleanup or optimization.
Quick Wins Checklist
If you're in a hurry, here are the highest-impact optimizations you can do right now:
- Run
resmon 1and identify the top 5 CPU-consuming resources - Check those resources for
Wait(0)loops and replace with appropriate delays - Remove any unused or duplicate scripts from your resources folder
- Add database indexes to your most-queried tables
- Enable OneSync distance culling
- Set up scheduled 8-hour restarts
- Reduce custom vehicle count if you have more than 80
All RARX scripts are built with performance as a core priority. We test every resource under load and optimize to under 0.02ms idle consumption. Performance is not an afterthought — it's a requirement.