Brazil's biggest MU Online portal — since 2003
Tutorial Advanced Server

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.

GA Gabriel · Updated on Dec 30, 2024 · ⏱ 17 min read
Quick answer

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.txt and .ini are 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):

ProcessChannel 1Channel 2Channel 3Exposed?
GameServer559015590255903Yes
DataServer555575556755577No
JoinServer555555556555575No
ServerCode012
ConnectServer44405 (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

SymptomLikely causeFix
Player enters the wrong channelServerList's ServerCode does not match the GameServer'sAlign the ServerCodes between the ServerList and each GameServer.ini
Channel does not appear in the selectionMissing entry or Visible=0 in the ServerListAdd/enable the entry and restart the ConnectServer
Character "disappears" when switching channelsChannels pointing to different databasesPoint them all at the SAME DSN/database
Second GameServer does not come upPort duplicated with the first channelAdjust the Channel 2 ports (Game/Data/Join)
One channel always full, another emptyNo crowding indicator/sortingEnable Fill/CurrentUsers and sort by least crowded
Lag persists after splittingBottleneck in the database, not the GameServerOptimize 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 .bat in 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.

GA
Guides & builds editor

Gabriel covers gameplay, class builds, PvP and progression. He tests every strategy on a live server before publishing.

Keep reading

Related articles