Running a Server

Killing Floor Dedicated Server Optimization - KillingFloor.ini Settings

Killing Floor Dedicated Server performance usually comes from stable networking, a clean KillingFloor.ini, fast redirect hosting for custom files, and a sensible tickrate. This guide turns the rough config notes into a practical KF1 server baseline and explains which values are worth changing first.

Before editing, stop the server and make a backup of System/KillingFloor.ini. Change one group of settings at a time and test after each group.

Quick baseline

AreaSafe starting pointChange it when
CacheSizeMegs128 or 256You run many custom maps, mutators, or slow map changes
NetServerMaxTickRate25 or 30CPU headroom and ping are both stable
MaxInternetClientRate10000 or 15000Players need more per-client bandwidth
HTTP redirectEnabledPlayers download maps from the game server
PrecacheKeep default firstYou have repeatable freezes or long loading stalls

For a public internet server, stable 25-30 tickrate is usually better than a higher tickrate that causes packet loss or late-wave stutters.

1. Cache and memory

[Engine.GameEngine]
CacheSizeMegs=256

Practical table:

Server RAMValue
256 MB or lessCacheSizeMegs=32
512 MBCacheSizeMegs=64
768 MBCacheSizeMegs=128
1 GB or moreCacheSizeMegs=256

Do not set a huge value just because the machine has spare RAM. With old UE2.5 servers, predictable behavior matters more than aggressive caching.

2. Network limits and tickrate

[IpDrv.TcpNetDriver]
MaxClientRate=15000
MaxInternetClientRate=10000
NetServerMaxTickRate=30
LanServerMaxTickRate=35
ServerTravelPause=4.0
SpawnPrioritySeconds=1.0
RelevantTimeout=5.0
KeepAliveTime=0.2
InitialConnectTimeout=200.0
ConnectionTimeout=15.0
AckTimeout=1.0
DownloadManagers=IpDrv.HTTPDownload
AllowDownloads=True

What matters

  • NetServerMaxTickRate=30 - server update rate. For public servers, 25-30 is usually enough.
  • LanServerMaxTickRate=35 - can be higher for LAN or private low-ping servers.
  • MaxClientRate and MaxInternetClientRate - upper bandwidth limit per player.
  • AllowDownloads=True - needed for custom files, but large maps should not be served directly by the game process.

If the server starts lagging during heavy waves, try lowering tickrate to 25 before cutting every bandwidth value.

3. HTTP redirect for maps and mutators

When players download custom maps from the game server itself, downloads consume bandwidth that should be serving active players. A production server should use HTTP redirect hosting.

[IpDrv.HTTPDownload]
RedirectToURL=https://example.com/kf-redirect/
UseCompression=True

Checklist:

  1. Redirect files must match the server files.
  2. Names and extensions must be exactly what the client expects.
  3. After updating a map or mutator, update redirect hosting at the same time.
  4. If players get Package version mismatch, check redirect files and client cache first.

Related fix: Package version mismatch.

4. Precache: keep it or disable it?

Disabling precache across several subsystems can make startup or map travel faster, but it can also move the stutter to the first spawn of a weapon, zed, or effect.

[ALAudio.ALAudioSubsystem]
UsePrecache=False

[Engine.LevelInfo]
bNeverPrecache=True

[Engine.NullRenderDevice]
UsePrecaching=False

[D3DDrv.D3DRenderDevice]
UsePrecaching=False

[D3D9Drv.D3D9RenderDevice]
UsePrecaching=False

[OpenGLDrv.OpenGLRenderDevice]
UsePrecaching=False

[PixoDrv.PixoRenderDevice]
UsePrecaching=False

For a dedicated server, stability matters most. If disabling precache creates micro-stutters at the start of waves or first content use, restore the previous values.

5. Corpses, gibs, and extra physics

For KF1, do not copy [KFGame.KFGoreManager] blocks from KF2 guides. In Killing Floor 1, look for settings that actually exist in your KillingFloor.ini and your active mutators.

[KFMod.KFGameType]
TimeUntilVanished=5.0

Very low values can look strange to players, but they can help weaker servers during large late waves and custom maps.

[IpServer.UdpServerQuery]
bEnabled=True

[IpDrv.MasterServerUplink]
DoUplink=True
SendStats=True
ServerBehindNAT=False
DoLANBroadcast=True

7. Paths and basic integrity

[Core.System]
CachePath=..\Cache
CacheExt=.uxx
Paths=..\System\*.u
Paths=..\Maps\*.rom
Paths=..\StaticMeshes\*.usx
SavePath=..\Save

Do not remove Paths for optimization. If the server stops seeing maps, mutators, or packages, check this block first.

  • Content from another folder. Paths lines can be duplicated with absolute paths so the server also loads files from another install and the same maps do not have to be copied. Example from krestps (killingfloor.ru forum, "Быстрая скачка В НЕСКОЛЬКО потоков" thread; he said it works for maps on the Steam version too):
Paths=../System/*.u
Paths=D:/killingfloor/System/*.u
Paths=../Maps/*.rom
Paths=D:/killingfloor/Maps/*.rom
Paths=../Textures/*.utx
Paths=D:/killingfloor/Textures/*.utx

The same thread confirmed that several RedirectToURL lines do not make redirect downloads multi-threaded.

8. Logs and operations

Do not disable useful logs completely. Use a separate log file per instance and clean old files on a schedule.

Good practice for multiple servers on one machine:

  • separate folder or separate config per instance
  • different game/query ports
  • separate log files
  • scheduled cleanup for old logs and temp files
  • monitor CPU during late waves, not only on an empty server

UE2.5 has limited multi-core scaling. If one process hits CPU limits, it is often better to split servers across instances/cores than to chase one magic config value.

Load measurements

Admins' figures from the "Server load on hardware" thread (2010-2012) and neighboring threads. These are old machines and individual observations, not benchmarks:

  • Max players per server matters more than the total. Proton: on an ordinary dual-core Celeron with 2 GB of RAM you can run 4-5 servers with up to about 20 players on each, CPU load around 20-25%, with almost no lag. But a single server with 30 slots on the same machine lags badly.
  • Linux vs Windows. NTFS: same machine, 6 players in the same spot on the map: Linux - CPU 30%, 43 degrees; Windows XP - CPU 60%, 51 degrees. Idle, XP loads the CPU 2-10% more. MAUOHE3, all with 6 players: 13% of one Q6600 core on CentOS 6, half that on CentOS 5, and 37% of one core of a Turion X2 2 GHz on Windows.
  • More examples. pingvus: Athlon XP 2200+, 768 MB, minimal console Linux - one classic 6-player server takes at most 50-55% CPU and about 350-370 MB of RAM together with the OS; with CpuLimit to spread the load, one more 6-player server fits. Локомотив: CentOS 5.7, 8-core Xeon, 3 GB - three 6-slot servers load at most 5-10%. offutt: a single-core Pentium 2.66 GHz with Hyper-threading (Win2003 R2) under a 14-slot KF server plus CS and Source servers hit 100% with rising ping; after moving to a dual-core CPU two KF servers ran on top with no problems.
  • Map change is the peak. REGETT ("AMD Athlon 64 3000+ vs Intel Celeron D" thread): on the Athlon 64 3000+ (1.8 GHz) - 10% idle, 18-23% in game, up to 80% for 10-15 seconds on a map change with 5 players; on the Celeron D (2.6 GHz) with Linux - 4-10% idle, 50-80% in game and 100% for 40-50 seconds on a map change with 3 players. After a week of testing he concluded the AMD handled the load better.
  • One core on Linux. In the "Is there multiprocessor support?" thread, Rush (Ubuntu 12.04, Core 2 Quad Q8300 2.5 GHz) saw in htop that the server loaded one core to 100% while the other three idled: the kernel was built with SMP, but the server could not use more than one core and only moved between them. Pir@tehnic suggested binding the server to cores through taskset, by putting taskset -c 0,1,2,3 in front of the usual start command screen -A -m -d -S KF-SERVER with the full path to the server binary in the KF server's System folder, but warned that in his experience with CS:Source this only pins the process and does not spread the load; with several servers each simply takes its own core. w.a.l stated that on Windows the server (UCC.exe) used all 4 cores for him.

Scrolling log in the console window (Windows)

From the killingfloor.ru forum "CMD LOG" thread: when text is printed quickly, cmd.exe keeps redrawing its window, which can load the machine more than the server itself. The simplest fix is to minimize the window. If you do not need the console text at all, redirect ucc output to nul: in the restart batch file, instead of start /wait ucc server ... run:

ucc server KF-Angkor.rom?game=*********?mutator=MutLoader.MutLoader?MaxPlayers=30?AdminName=*****?AdminPassword=******* > nul

All text output from ucc.exe is then discarded, but the server still writes its log file.

Auto-restart batch file with timestamped logs

A batch file by Dr_Killjoy from the killingfloor.ru forum "Автоматический перезапуск сервера" thread (server 1060 era). Map, game type, ini, admin and player count are variables at the top. The batch file keeps its own log in the KFLogs folder (showing when the server crashed), and each server log is named with its start time, so old logs are not overwritten. The batch file goes in the server root (next to the System folder); replace the admin login and password with your own:

:begin
@echo off
title KF Server
setlocal enabledelayedexpansion
set workdir=%cd%
set sdir=%workdir%\system
set batlogdir=%cd%\KFLogs
if not exist %batlogdir% md %batlogdir%
:retry
call :settime
set map=KF-Farm.rom
set gametype=KFMod.KFGameType
set adminlogin=<login>
set adminpass=<password>
set maxplayers=6
set kfini=KillingFloor.ini
set mutators=MutLoader.MutLoader
set batlog=runserver#1.bat
set batlog=%batlogdir%\%batlog%_%now%.log
set kflog=KFServer_%now%.log
if not exist %sdir%\ucc.exe call :notfounducc
call :echolog "Server started/restarted at %now% ..."
set callucc="%sdir%\ucc.exe" server %map%?game=%gametype%?VACSecured=true?MaxPlayers=%maxplayers%?Mutator=%mutators%?AdminName=%adminlogin%?AdminPassword=%adminpass% -ini=%kfini% -log=%kflog%
call :echolog "%callucc%"
call %callucc%
call :settime
call :echolog "Server crashed at %now% ..."
goto retry
exit /b
:settime
set now=%TIME:~0,-3%
set now=%now::=.%
set now=%now: =0%
set now=%DATE:~-4%.%DATE:~3,2%.%DATE:~0,2%.%now%
exit /b
:notfounducc
call :echolog "ucc.exe has not been found"
pause
goto end
:echolog
echo %~1
echo %~1>%batlog%
exit /b
:end

Minimal production profile

[Engine.GameEngine]
CacheSizeMegs=256

[IpDrv.TcpNetDriver]
MaxClientRate=15000
MaxInternetClientRate=10000
NetServerMaxTickRate=30
LanServerMaxTickRate=35
ServerTravelPause=4.0
SpawnPrioritySeconds=1.0
RelevantTimeout=5.0
KeepAliveTime=0.2
InitialConnectTimeout=200.0
ConnectionTimeout=15.0
AckTimeout=1.0
DownloadManagers=IpDrv.HTTPDownload
AllowDownloads=True

[IpServer.UdpServerQuery]
bEnabled=True

[IpDrv.MasterServerUplink]
DoUplink=True
SendStats=True
ServerBehindNAT=False
DoLANBroadcast=True

After that, configure HTTP redirect, test late waves with 6 players, and only then experiment with precache, corpse lifetime, and higher tickrate.