When a Garry's Mod server lags, the cause is almost always Lua - one addon doing too much work every tick, or erroring every tick - or physics, from too many props touching each other. It is rarely the hardware, and almost never fixed by a bigger plan alone. The working method is short: read the console for repeating Lua errors and fix or remove the addon that throws them, measure server frame time with stats while the lag is happening, profile hooks with a profiler addon to find which one is expensive, and bisect the addon list on a test copy when nothing else names a culprit. Then set a sane tickrate, prop limits and a nightly restart so it stays fixed. This guide goes through each step with the commands.
Where the time goes on a Garry's Mod server#
A Garry's Mod server runs its game simulation on one thread. Each tick - 66 times a second at -tickrate 66, 33 at -tickrate 33 - it runs physics, entity logic and every Lua hook registered by the gamemode and addons, then sends updates to players. If the work for one tick takes longer than the tick interval (15 ms at 66 tick), the server falls behind and players feel it as rubber-banding, delayed shots and props that stutter.
| Source of cost | Typical symptom | Where to look |
|---|---|---|
| A Lua hook doing heavy work per tick | Lag that grows with player count | Profiler, addon bisect |
| A Lua error inside a hook | Console spam, constant mild lag | Console, error log |
| Physics: many props in contact | Lag when someone builds or a pile collapses | Prop count, physics settings |
| Net messages: too much sent at once | Players disconnect with overflow errors | Client console, addon bisect |
| Database queries on the main thread | Spikes on join, death or round end | Addons using SQL, sv.db size |
| Memory pressure | Crash after hours or days | Memory graph, 32-bit vs 64-bit |
The order matters. Lua errors are the cheapest to find and the most common, so start there. Garry's Mod server setup covers the base install and a first diagnostic pass; this post goes deeper.
Reading Lua errors#
A Lua error prints to the server console with the file, the line and a stack trace:
[ERROR] addons/coolhud/lua/autorun/server/sv_hud.lua:42: attempt to index a nil value 1. fn - addons/coolhud/lua/autorun/server/sv_hud.lua:42 2. unknown - lua/includes/modules/hook.lua:96Read it from the top. The first line says which file and line failed and why; the path names the addon (coolhud here, or the Workshop addon's title for Workshop content). The stack shows what called it - hook.lua means it ran from a hook, which means it will run again next tick, and the tick after.
Common messages and what they usually mean:
| Message | Usual cause |
|---|---|
attempt to index a nil value | Code assumed a player, entity or table existed and it did not |
attempt to call a nil value | A function from another addon or a removed API is missing |
attempt to compare number with nil | A config value or networked variable was never set |
Tried to use a NULL entity! | An entity was removed while code still used it |
bad argument #1 to ... | Wrong type passed, often after a Garry's Mod update changed something |
stack overflow | Infinite recursion, often two addons hooking each other |
The one that matters most for performance is an error inside a hook that runs every tick. The error handler itself costs time, the console fills with spam, and the log grows. A single broken HUD addon erroring in a Think hook for every player can cost more than the rest of the addon list combined.
Getting errors you can read later
The live console scrolls too fast to read on a busy server. Two settings help:
con_logfile "console.log"lua_log_sv 1con_logfile writes everything the console prints to a file under garrysmod/, and lua_log_sv 1 asks the server to log its Lua errors as well. Both files grow; delete or rotate them weekly. Reading the console covers which lines matter and which are noise.
Client-side errors - in HUDs, menus and effects - happen on each player's machine and appear in their console, not yours. If players report errors you never see, ask for a screenshot of their console after typing lua_log_cl 1; the path in the error still names the addon.
Fixing or removing an erroring addon#
Once the console names an addon, there are four options, in order of preference:
- Update it. Many errors appear after a Garry's Mod update changed an API, and the author has already fixed it. Workshop addons update themselves on restart; legacy addons in
garrysmod/addons/do not. - Check for a conflict. An addon that works alone and fails with another installed usually means both override the same function or hook name. Remove the other one and test.
- Fix it yourself. If you can read Lua, the file and line are right there. A nil check (
if not IsValid(ent) then return end) fixes a large share of real-world errors. - Remove it. An abandoned addon throwing errors every tick is not worth keeping. Unsubscribe it from the collection or delete its folder.
Do not silence errors by wrapping them in pcall everywhere. That hides the error and keeps the cost.
Measuring: stats, status and a profiler#
You cannot fix lag you have not measured. Three tools, from cheapest to most detailed.
stats in the server console prints CPU usage, incoming and outgoing traffic, uptime, the number of map changes and the server's frame rate. Run it during lag. If the frame rate is below the tickrate, the server cannot keep up - a server problem. If it is at the tickrate and players still complain, look at their connection and at net messages instead.
status lists players with their ping and loss. One player with 400 ms and loss is that player's route; everyone at 400 ms is the server. Latency, jitter and packet loss explains the difference.
A profiler shows which Lua functions use the time. FProfiler is the long-standing Garry's Mod profiling addon: install it, start a recording while the server is busy, stop it after a minute, and it lists the most expensive hooks and functions with their total and average time. That list is usually decisive - one hook from one addon at the top with ten times the cost of anything else.
Quick checks with lua_run from the server console are also useful:
lua_run print(#ents.GetAll())lua_run print(#player.GetAll())lua_run print(collectgarbage("count"))The first prints the entity count, which on a sandbox or DarkRP server tells you whether props are piling up. The last prints Lua memory in kilobytes; if it climbs steadily over hours and never falls back, an addon is leaking tables.
Addon cost: what makes an addon expensive#
Some patterns are reliably expensive, and recognising them in a profiler result saves time:
- Per-tick loops over players or entities. A
ThinkorTickhook that callsplayer.GetAll()orents.FindInSphereand does work for each result. Cheap at 10 players, expensive at 60. - Timers with tiny intervals.
timer.Createwith a delay of0or0.01, repeating forever. Effectively another per-tick hook. - Networking in hooks. Sending net messages to all players every tick, or networking large tables. Costs bandwidth as well as CPU and causes overflow disconnects.
- File and SQL access in hooks. Reading or writing files, or running
sql.Queryagainst the local SQLite database, inside a frequent hook. Both block the game thread. - Physics-heavy entities. Vehicles, ropes, wire contraptions and anything that spawns many physics objects.
When nothing obvious shows up, bisect. Make a copy of the server on a test instance, remove half the addons, and measure under the same load. Keep halving until the lag follows one addon. It is tedious, and it is the only method that always works.
A typical case, start to finish
A roleplay server runs fine with twenty players and drags at forty. Nothing in the console. stats during peak shows the server frame rate falling to the low twenties against a tickrate of 33, so the server is genuinely behind. A one-minute profiler recording puts one function at the top: a hook from an HUD-adjacent addon that, every tick, loops over every player and for each one loops over every entity to find the nearest door. Forty players times a few thousand entities, 33 times a second.
Nothing about that hook was broken. It worked, it threw no errors, and at twenty players it cost a millisecond per tick. At forty players the cost quadrupled, because both lists had doubled. The fix was to run the same check once a second instead of every tick, which the addon's config allowed and nobody had looked at. Frame rate went back to the tickrate, and the plan did not change.
That is the shape of most Garry's Mod performance problems: not a bug, but work that scales with players times entities, hidden in an addon that looked harmless at launch. The profiler finds it in minutes; guessing takes weeks.
Physics, props and limits#
Physics runs every tick too, and it gets expensive non-linearly: a hundred props lying still are cheap; a hundred props piled together and touching are not, because every contact is resolved every tick. On sandbox and roleplay servers, the worst lag usually comes from one player's contraption or a deliberate prop pile.
sbox_maxprops 150sbox_maxragdolls 5sbox_maxvehicles 2sbox_maxeffects 50sbox_maxballoons 10sbox_maxthrusters 20sbox_noclip 1These limits are per player. Keep them as low as your gamemode allows; a sandbox server with sbox_maxprops 1000 and thirty players can in theory hold thirty thousand props. Add a prop-cleanup-on-disconnect setting in your admin mod or a cleanup addon, and consider an anti-crash addon that freezes props when too many collide at once. TTT and other round-based modes clean up every round and need far less of this. The TTT server guide covers that gamemode specifically.
Tickrate, hibernation and memory#
-tickrate on the launch line sets how many ticks the server runs per second. 66 is smoother; 33 halves the per-tick cost and is still fine for roleplay and sandbox where precise aim matters less. Set it explicitly rather than relying on a default.
| Gamemode | Sensible tickrate | Why |
|---|---|---|
| Sandbox, DarkRP, roleplay | 33 | Many entities, aim matters less |
| TTT, Murder, Prop Hunt | 33-66 | Round-based, moderate entity counts |
| Combat-focused gamemodes | 66 | Aim and hit registration matter |
Raising the tickrate roughly doubles the per-tick CPU cost and makes no difference to a server that is already behind. Fix the cost first, then raise the rate if there is headroom. What tick rate actually means has the longer argument.
An empty Garry's Mod server hibernates by default and uses almost no CPU. sv_hibernate_think 1 keeps it thinking while empty, which some addons need; if your idle server shows steady CPU use, check whether this is set, or whether an addon is running a timer regardless.
Memory problems look different. The standard Garry's Mod server is a 32-bit process, so it can only address about 4 GB however much the plan has; large collections hit that ceiling and crash with out-of-memory errors while the graph looks fine. The x86-64 beta branch removes that limit, at the cost of needing 64-bit builds of any binary modules. The local SQLite database, garrysmod/sv.db, is another slow leak: some addons write to it constantly, and a file of hundreds of megabytes makes every query slower. Check its size occasionally and clean or move the data that addons store there.
Restarts, crashes and staying fixed#
Even a well-tuned Garry's Mod server accumulates entities, timers and Lua memory over days. A nightly restart at an empty hour keeps frame times flat and costs nothing. On RE:NODE the Schedules tab runs it from a cron expression, with an optional warning command a few minutes before. Restart schedules that help covers timing.
Crashes are a separate problem from lag. A Lua error does not crash the server; a crash comes from a binary module, a physics explosion, the 32-bit memory ceiling or the process being stopped at the plan's memory limit. On RE:NODE a server that reaches its memory limit is stopped and restarted clean rather than left to swap, and a watcher counts unexpected restarts - three in an hour puts a warning on the server page and opens a ticket automatically, so a crash loop does not go unnoticed. Why your game server keeps restarting helps tell those cases apart.
Troubleshooting#
The console is full of the same Lua error. One addon in a hook. Read the path in the first line, update or remove that addon, and restart.
Lag only when the server is full. Per-player cost. Profile at peak; look for hooks looping over players.
Lag spikes when someone joins. Addons doing database or file work on PlayerInitialSpawn, or a large sv.db. Profile a join.
Players disconnect with "reliable channel overflowed". An addon sends too much in one go, usually on spawn. Remove addons until it stops; the client console shows the last message received.
The server crashes after hours with memory free. The 32-bit address space. Trim addons or move to the 64-bit branch with matching modules.
Idle server uses CPU. sv_hibernate_think 1, or an addon timer running without players.
FAQ#
Do Lua errors cause lag?
An error that happens once does not matter. An error inside a hook that runs every tick does, because the error handler runs every time and the console and log fill up. Fix repeating errors first.
What tickrate should a Garry's Mod server use?
33 for sandbox and roleplay, 33 to 66 for round-based modes, 66 for combat-focused gamemodes. Put it on the launch line explicitly, and only raise it once the server has CPU headroom at peak.
Will a bigger plan fix my lag?
Only if the server is genuinely short of CPU or memory after the addon problems are fixed. One expensive hook or a pile of colliding props will lag on any hardware. Measure first, then size.
How do I find which addon is causing lag?
Read the console for repeating errors, then use a profiler such as FProfiler while the server is busy. If neither names a culprit, remove half the addons on a test copy and measure, repeating until the lag follows one addon.
Should I run the 64-bit Garry's Mod server?
If your server crashes with memory errors while the plan has memory to spare, yes. Check that every binary module you use has a 64-bit build first.




Comments
Completely anonymous: no account, no email, no cookie. We store the name you type, the text and the time - nothing else. Links are limited and markup is not rendered.