How to set up sub-servers (channels) in MU Online
Learn how to split your MU Online server into multiple channels (sub-servers) that share the same database, distributing the player load across instances and knowing the right moment to split.
As a MU Online server grows, the moment comes when a single GameServer can no longer handle the volume of simultaneous players: lag starts appearing in crowded areas, delays in events, and CPU spikes that degrade everyone's experience at once. The classic answer to this is to split the server into s
As a MU Online server grows, the moment comes when a single GameServer can no longer handle the volume of simultaneous players: lag starts appearing in crowded areas, delays in events, and CPU spikes that degrade everyone's experience at once. The classic answer to this is to split the server into sub-servers, also called channels — multiple GameServer instances that share the same database and the same characters, but distribute the players across separate processes. The player is still the same on any channel; they only choose, on the selection screen, which instance to enter. This model increases total capacity, reduces concentration on a single instance and even allows more granular maintenance. This tutorial covers the multi-channel architecture, port configuration, the ConnectServer's ServerList, player-balancing strategies and — most importantly — the right moment to split, so you don't add complexity before it's needed.
What channels (sub-servers) are
A channel is a GameServer instance that is part of the same logical server. All the channels of a server:
- Share the same database — accounts, characters, items, guild, ranking are single and unique.
- Appear on the same selection screen (Channel 1, Channel 2...), served by the same ConnectServer.
- Have the same content — maps, drops, rates are usually identical (although it is possible to differentiate rates per channel, that is not the most common use).
The essential difference from running two separate servers is the shared database. With channels, the character "Warrior01" exists only once and can enter through any channel. This is fundamental: channels serve to scale capacity, not to create different worlds.
Multi-channel architecture
The typical design with a single database and several GameServers:
SQL DATABASE (single)
│
┌──────────┼──────────┐
│ │ │
DataServer DataServer DataServer
│ │ │
JoinServer JoinServer JoinServer
│ │ │
GameServer GameServer GameServer
Channel 1 Channel 2 Channel 3
(port 55901)(port 55902)(port 55903)
│ │ │
└──────────┼──────────┘
│
ConnectServer
(port 44405)
│
PLAYER
(sees the channel list)
Each channel is a complete stack (DataServer + JoinServer + GameServer) pointing to the same database. The ConnectServer centralizes the connections and shows the available channels.
Prerequisites
- A working MU Online server with a single stable channel. If you are still building the base server, see the how to create a MU Online server guide.
- A machine (VPS/dedicated) with resource headroom — each additional channel consumes CPU and RAM.
- SQL Server with the single database (standard MuOnline) and a 32-bit ODBC DSN configured.
- Administrative access to open ports in the firewall.
- A text editor that preserves encoding (Notepad++/VS Code), since
ServerList.txtand.iniare sensitive. - A clear understanding that all channels use the same database — never point a channel at another database by mistake.
- A full backup before any change.
> Do not confuse channels with independent servers. If you point each channel at a different database, you no longer have channels but two disconnected servers. The shared database is what defines the model.
Step 1 — Folder structure per channel
Each channel needs its own folder and its own configuration files:
MuServer/
├── Channel1/
│ ├── DataServer/
│ ├── JoinServer/
│ └── GameServer/
├── Channel2/
│ ├── DataServer/
│ ├── JoinServer/
│ └── GameServer/
└── ConnectServer/
├── ConnectServer.exe
└── ServerList.txt
The ConnectServer is single and serves all channels — it is not duplicated.
Step 2 — Ports per channel
Since all channels live on the same machine, each network process needs a unique port. Only the database is shared. An example scheme (the keys and ports vary by emulator):
| Process | Channel 1 | Channel 2 | Channel 3 | Exposed? |
|---|---|---|---|---|
| GameServer | 55901 | 55902 | 55903 | Yes |
| DataServer | 55557 | 55567 | 55577 | No |
| JoinServer | 55555 | 55565 | 55575 | No |
| ServerCode | 0 | 1 | 2 | — |
| ConnectServer | 44405 (shared) | Yes |
The ServerCode (also called the server code) must be unique per channel and match what is in the ServerList.
Step 3 — Configure the GameServers
Each channel gets a GameServer.ini with its ServerCode and its ports, but with the same DSN:
; Channel1/GameServer/GameServer.ini
[General]
ServerCode=0
ServerName=Channel 1
[Network]
GameServerPort=55901
[JoinServer]
JoinServerIP=127.0.0.1
JoinServerPort=55555
[Database]
DSN=MuOnline ; the same database on ALL channels
; Channel2/GameServer/GameServer.ini
[General]
ServerCode=1
ServerName=Channel 2
[Network]
GameServerPort=55902 ; different port
[JoinServer]
JoinServerIP=127.0.0.1
JoinServerPort=55565 ; different port
[Database]
DSN=MuOnline ; SAME database
Do the same for each channel's DataServer.ini and JoinServer.ini, always with distinct ports and the same DSN.
Step 4 — Configure the ConnectServer's ServerList
The ConnectServer reads the list of channels and presents it to the client. The classic ServerList.txt format (varies by emulator; some distros use Setting.xml):
; ServerList.txt
; Format: Index IP Port Name MaxUsers Fill
; Fill = visual crowding indicator (0=empty ... 30=full)
0 YOUR_IP 55901 "Channel 1" 1000 0
1 YOUR_IP 55902 "Channel 2" 1000 0
2 YOUR_IP 55903 "Channel 3" 1000 0
XML version, common in more recent distributions:
<?xml version="1.0" encoding="utf-8"?>
<ServerList>
<Server>
<ServerCode>0</ServerCode>
<ServerName>Channel 1</ServerName>
<IP>YOUR_IP</IP>
<Port>55901</Port>
<MaxUsers>1000</MaxUsers>
<Visible>1</Visible>
</Server>
<Server>
<ServerCode>1</ServerCode>
<ServerName>Channel 2</ServerName>
<IP>YOUR_IP</IP>
<Port>55902</Port>
<MaxUsers>1000</MaxUsers>
<Visible>1</Visible>
</Server>
</ServerList>
Each entry's ServerCode must match the ServerCode in the corresponding GameServer.ini, or the player is sent to the wrong channel.
Step 5 — Firewall
Open only the ConnectServer and the GameServers; keep the DataServer and JoinServer internal:
netsh advfirewall firewall add rule name="MU Connect" dir=in action=allow protocol=TCP localport=44405
netsh advfirewall firewall add rule name="MU Ch1" dir=in action=allow protocol=TCP localport=55901
netsh advfirewall firewall add rule name="MU Ch2" dir=in action=allow protocol=TCP localport=55902
# DataServer/JoinServer (55557,55555,55567,55565): DO NOT expose to the internet
Step 6 — Startup order
Bring up each channel's processes in the canonical order and leave the ConnectServer for last:
@echo off
start "" "MuServer\Channel1\DataServer\DataServer.exe"
timeout /t 3
start "" "MuServer\Channel1\JoinServer\JoinServer.exe"
timeout /t 3
start "" "MuServer\Channel1\GameServer\GameServer.exe"
timeout /t 5
start "" "MuServer\Channel2\DataServer\DataServer.exe"
timeout /t 3
start "" "MuServer\Channel2\JoinServer\JoinServer.exe"
timeout /t 3
start "" "MuServer\Channel2\GameServer\GameServer.exe"
timeout /t 5
start "" "MuServer\ConnectServer\ConnectServer.exe"
echo All channels are up.
Player balancing
Distributing players evenly across channels is what secures the performance benefit. Common strategies:
- Crowding indicator (Fill/CurrentUsers): make the ConnectServer reflect the real occupancy. That way players themselves tend to choose the less crowded channel.
- Sort the list by least crowded: some distros allow the channel with fewer people to appear first.
- MaxUsers per channel: set a cap per channel so that, when full, it stops accepting connections and pushes new players to another.
- Active monitoring: track the distribution through the database.
-- Online per channel (if the GameServer records the session with ServerCode)
SELECT ServerCode, COUNT(*) AS Online
FROM GameServerSessions -- table name varies by distribution
WHERE IsOnline = 1
GROUP BY ServerCode
ORDER BY Online DESC;
-- Overall online total
SELECT COUNT(*) AS TotalOnline
FROM Character
WHERE ConnectStat = 1;
Remember that, because they share the database, items in personal shops, guild, ranking and trades stay consistent across the channels — the player switches channel without losing anything.
When to split into channels (and when not to)
Split when: your single channel approaches the emulator's practical limit of simultaneous players; you observe lag and high CPU concentrated at peak times; or specific areas (cities, event spots) become impassable from being so crowded. Do not split too early: a freshly launched server, with a few dozen online, only gains maintenance complexity with no real benefit from multiple channels. As a rule of thumb, keep a single channel while it is comfortable and add the second when peak occupancy consistently exceeds around 70% of the first's stable capacity.
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Player enters the wrong channel | ServerList's ServerCode does not match the GameServer's | Align the ServerCodes between the ServerList and each GameServer.ini |
| Channel does not appear in the selection | Missing entry or Visible=0 in the ServerList | Add/enable the entry and restart the ConnectServer |
| Character "disappears" when switching channels | Channels pointing to different databases | Point them all at the SAME DSN/database |
| Second GameServer does not come up | Port duplicated with the first channel | Adjust the Channel 2 ports (Game/Data/Join) |
| One channel always full, another empty | No crowding indicator/sorting | Enable Fill/CurrentUsers and sort by least crowded |
| Lag persists after splitting | Bottleneck in the database, not the GameServer | Optimize indexes/queries; check the disk (SSD) |
Launch checklist
- Full backup of the server and the database taken
- Need for channels confirmed by occupancy/CPU data
- A separate folder for each channel
- Unique ports per process in each channel (Game/Data/Join)
- Unique ServerCode per channel
- All channels pointing to the SAME DSN/database
- ServerList (or Setting.xml) with one entry per channel and matching ServerCodes
- Firewall opening only the ConnectServer and GameServers
- DataServer/JoinServer closed off from the internet
- Crowding indicator/MaxUsers configured for balancing
- Startup
.batin the correct order - Test: the client sees all channels in the selection
- Test: enter each channel and confirm the same character
- Test: switch channels without losing items/guild/ranking
- Online-per-channel monitoring working
With channels well configured — unique ports, aligned ServerCodes and a single shared database — your MU Online server scales to many more simultaneous players without sacrificing stability. Adopt the split guided by occupancy data, validate the channel switch with real character tests, and keep an eye on balancing at all times so that the extra capacity translates into smooth gameplay for everyone.
Frequently asked questions
What is the difference between channels and independent servers?
Channels (sub-servers) share the SAME database and the SAME characters — the player is the same on any channel, just distributed across different instances to ease the load. Independent servers have separate databases, accounts and characters. A channel is about capacity; a separate server is about distinct projects.
How many channels should I create?
Start with the minimum needed. A single GameServer usually handles from a few hundred to more than a thousand players depending on the emulator and the hardware. Only add a second channel when the first approaches the practical limit of simultaneous players or of CPU.
Do channels need different ports?
Yes. Each GameServer/channel on the same machine needs a unique port (e.g., 55901, 55902, 55903). Each channel's DataServer and JoinServer also need their own ports. Only the database is shared.
How does the player choose the channel?
Through the ConnectServer. It reads the ServerList and presents the client with the list of available channels (Channel 1, Channel 2...), often with a crowding indicator. The player chooses and is redirected to that channel's GameServer.
Can I have channels on different machines?
Yes. On large servers, each channel can run on a separate VPS, all pointing to the same central database. The ConnectServer's ServerList uses the real IPs of each machine. This requires low latency between the servers and the database.