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

How to set up a load balancer for your MU Online server

Distribute the load of your MU Online server's ConnectServer and website across multiple instances with a load balancer, reducing lag during peak hours and increasing infrastructure resilience.

BR Bruno · Updated on Jul 31, 2026 · ⏱ 17 min read
Quick answer

As a MU Online server grows, the first scaling pain usually shows up at login: connection queues, ConnectServer timeouts, or the site going down right during peak hours, when the most players try to log in at once. A load balancer distributes this load across multiple instances of the same service,

As a MU Online server grows, the first scaling pain usually shows up at login: connection queues, ConnectServer timeouts, or the site going down right during peak hours, when the most players try to log in at once. A load balancer distributes this load across multiple instances of the same service, preventing a single process or machine from becoming a bottleneck. This tutorial shows how to apply load balancing at the ConnectServer, site, and auxiliary API layer of a MU server, including a practical Nginx setup, health checks, and load testing.

What can (and can't) be balanced on a MU server

The typical MU Online server architecture has components with very different scaling characteristics:

ComponentKeeps per-player state?Ease of balancing
GameServer (game world)Yes, full session and map stateHard — usually scales via sharding (multiple servers/worlds), not traditional load balancing
ConnectServerNo, only routes to the correct GameServerEasy — multiple instances behind a balancer
Institutional site/storeNo (or state in a database/external session)Easy — standard pattern for any web application
Admin panel APIDepends on implementationGenerally easy, if stateless
DatabaseYes, it's the source of truthScales via replication/read replicas, not simple load balancing

Understanding this table avoids the mistake of trying to "put a load balancer in front of the GameServer" expecting it to fix map lag — that doesn't work the same way, because game state lives inside a specific process.

Scenarios that justify a load balancer

Before investing time in configuration, confirm the symptom matches the right problem:

  • Connection queue or timeout on the ConnectServer during peak hours, even with normal CPU/RAM.
  • Site or store down exactly when the server is most crowded (event, season reset).
  • Slow admin panel for staff during the same peaks.

If the symptom is lag inside the game maps, the problem is probably somewhere else (script optimization, monster count, the GameServer's own database) — it's worth investigating that separately before assuming a lack of load balancing is the cause.

Reference architecture with Nginx

A simple, effective architecture to start with uses Nginx as a load balancer in front of multiple site/API instances and, where applicable, the ConnectServer:

                    ┌──────────────┐
   Players    ──►   │  Nginx (LB)  │
                    └──────┬───────┘
              ┌────────────┼────────────┐
              ▼            ▼            ▼
        Instance 1    Instance 2    Instance 3
        (site/API)    (site/API)    (site/API)

Configuring site load balancing with Nginx

A basic upstream block in nginx.conf distributes HTTP requests across multiple instances of the site application:

upstream mu_site_backend {
    least_conn;
    server 127.0.0.1:3001;
    server 127.0.0.1:3002;
    server 127.0.0.1:3003;
}

server {
    listen 80;
    server_name yoursite.com;

    location / {
        proxy_pass http://mu_site_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

The least_conn directive routes each new request to the instance with the fewest active connections at that moment, preventing one instance from getting overloaded while another sits idle — generally more effective than plain round-robin for irregular traffic like that of a MU server.

Health checks: automatically removing failed instances

A load balancer without health checking keeps sending traffic to a frozen instance, making the experience worse instead of better. Set up a simple health check endpoint in the application (e.g., /health, returning 200 if healthy) and, in Nginx (or using the nginx_upstream_check_module module / solutions like HAProxy for more robust active checking), monitor that endpoint periodically:

upstream mu_site_backend {
    server 127.0.0.1:3001 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:3002 max_fails=3 fail_timeout=30s;
}

With max_fails and fail_timeout, Nginx stops sending traffic to an instance after 3 consecutive failures, giving it 30 seconds before trying again — reducing the impact of a frozen instance on players.

Balancing the ConnectServer

The ConnectServer is responsible for authenticating the initial connection and directing the client to the correct GameServer — it doesn't hold the game session state itself, which makes it easier to replicate across multiple instances. The most common approach is running 2 or more ConnectServer instances on different ports (or machines) and using a layer-4 (TCP) balancer, since the ConnectServer protocol isn't HTTP:

frontend mu_connect
    bind *:44405
    mode tcp
    default_backend mu_connect_pool

backend mu_connect_pool
    mode tcp
    balance leastconn
    server connect1 127.0.0.1:44406 check
    server connect2 127.0.0.1:44407 check

This example uses HAProxy-style syntax, more suitable than plain Nginx for low-level TCP balancing like the ConnectServer's — Nginx also supports stream for this, but HAProxy tends to be the more mature choice in this specific scenario.

Session and affinity (sticky sessions)

For the site and admin panel, if the application stores login sessions in local memory (not in a shared database/Redis), "sticky sessions" need to be configured — ensuring the same player/admin always lands on the same instance during their session, avoiding unexpected logouts when redirected to another instance. The more robust solution, however, is migrating session storage to a shared store (Redis, database), making any instance interchangeable and balancing simpler and more resilient.

Testing balancing under load

Before trusting the configuration in production, simulate concurrent traffic with a load-testing tool (ab, wrk, or k6):

wrk -t4 -c200 -d30s http://yoursite.com/

This command simulates 200 concurrent connections for 30 seconds using 4 threads. During the test, watch whether the load is distributed evenly across instances (via Nginx/HAProxy logs or metrics) and whether response time stays stable even under this volume.

Monitoring the load balancer in production

Once active, continuously monitor:

MetricWhere to observeWhy it matters
Requests per instanceNginx/HAProxy logs or exposed metricsDetects load imbalance
Response time per instanceAPM or logs with request timingIdentifies a degraded instance
Health check failuresLoad balancer logsAlerts before the player notices
CPU/RAM usage per instanceSystem monitoring (htop, Grafana)Confirms the balancing is actually distributing load

Scaling gradually as your base grows

You don't need to start with an elaborate multi-physical-machine architecture. A common evolution path:

  1. A single site/ConnectServer instance, no load balancer (initial phase).
  2. Multiple instances on the same VPS, balanced locally by Nginx (growth phase).
  3. Multiple instances on different VPSs, with a dedicated balancer and Redis-shared session (scale phase).
  4. Geographic balancing (multiple data centers/regions), reserved for large servers with an international base.

Moving to the next phase before it's needed just adds operational complexity without real benefit — scale according to actual overload symptoms as they appear.

Common errors and fixes

SymptomLikely causeFix
Player logged out when reloading the siteSession in local memory with no sticky session or shared storageMigrate session to Redis/database or configure sticky sessions
Balancer keeps sending traffic to a frozen instanceNo health check configuredConfigure a health endpoint and max_fails/fail_timeout
ConnectServer doesn't distribute connections correctlyBalancing configured as HTTP instead of TCPUse TCP mode (stream/HAProxy) for the ConnectServer
One instance always more overloaded than the othersSimple round-robin algorithm with irregular loadSwitch to least_conn or least-active-connection balancing
Lag persists even after balancing the siteThe real bottleneck is the GameServer/database, not the siteInvestigate the GameServer and database separately

Load balancer configuration checklist

  • Components correctly identified (what can and can't be balanced).
  • Multiple site/API instances configured and tested individually.
  • Balancer (Nginx/HAProxy) configured with an appropriate algorithm (least_conn).
  • Health checks configured for automatic removal of failed instances.
  • Shared session (Redis/database) configured, if applicable.
  • Dedicated TCP balancing for the ConnectServer, if needed.
  • Load test performed before releasing to production.
  • Continuous monitoring of requests, response time, and failures per instance.

With the connection layer and auxiliary services ready for access spikes, it's worth reviewing your environment's baseline setup — check the MU Online server setup tutorial to confirm the GameServer and database are also sized for your community's growth.

Frequently asked questions

Does a load balancer also work for the GameServer, or only for the site/ConnectServer?

The main GameServer (the game world) usually isn't balanced the same way, because it keeps every player's session state in a single process. What's easier to balance are the ConnectServer (authentication/initial routing), the site, and auxiliary APIs.

Do I need multiple physical servers to use a load balancer?

Not necessarily at first. You can run multiple ConnectServer or site instances in separate containers/processes on the same robust VPS, and use the load balancer to distribute between them, migrating to separate physical machines as growth demands it.

Is Nginx enough, or do I need a dedicated load balancer (HAProxy, etc)?

Nginx already handles most cases well for a small-to-medium MU server, both for the site and for ConnectServer proxying. HAProxy comes into play when you need more advanced layer-4 (TCP) balancing features with high performance.

How do I know if I really need a load balancer?

Clear signs are: login lag during peak hours even with normal CPU/RAM on the application, a connection queue on the ConnectServer, or traffic spikes on the site slowing down the admin panel's response. If your base is still small and stable, simpler optimizations may suffice before this step.

Does a load balancer fix lag inside the game world itself (maps)?

Not directly. Lag inside the world is usually a limitation of the GameServer/map itself (too many players on the same map, too many monsters, heavy scripts). A load balancer helps at the connection layer and auxiliary services, it doesn't replace optimizing the emulator itself.

BR
Events, maps & items editor

Bruno specializes in MU Online events, maps, bosses and item economy. He documents every detail based on real gameplay.

Keep reading

Related articles