A single Jitsi Meet server runs out of videobridge capacity long before anything else. The good news is that Jitsi was designed to scale out: you don't need a bigger server, you need more bridges, and eventually more shards. This guide covers both, with the current configuration format. It replaces two older articles of ours that used sip-communicator.properties and HAProxy directives that newer versions no longer accept.

Two levels of load balancing

More bridges in a shard More shards
What you add Videobridge servers Complete Jitsi deployments (nginx, Prosody, Jicofo, bridges)
Who balances Jicofo, automatically HAProxy, by room name
Solves Bridge CPU and bandwidth Prosody and Jicofo limits, failure isolation
Complexity Low Medium

Start with bridges. Most deployments never need a second shard, and you only find out whether you do by measuring. Load testing Jitsi Meet shows how, and the Jitsi handbook's scalable setup guide is the upstream reference for both levels.

Horizontal scaling: add videobridges to a shard

The main server keeps nginx, Prosody and Jicofo, and its own bridge. The new server runs only a videobridge that logs in to the main server's Prosody and joins the same brewery room. Jicofo notices it and starts using it.

1. Let the bridge reach Prosody

Bridges log in over XMPP on TCP 5222. On the main server, allow that port from the new bridge's private IP only:

sudo ufw allow from 10.0.1.30 to any port 5222 proto tcp

Never open 5222 to the internet for this. In a cloud VPC, do the same with a security group rule scoped to the bridge.

While you are on the main server, copy the bridge account password from its own config:

sudo grep -A8 'shard' /etc/jitsi/videobridge/jvb.conf

2. Install the bridge on the new server

Add the Jitsi repository exactly as in step 5 of installing Jitsi Meet on Ubuntu, open UDP 10000, then install only the videobridge:

sudo apt install -y jitsi-videobridge2

When it asks for the hostname, enter the main Jitsi domain, for example meet.example.com.

3. Point it at the main server

Edit /etc/jitsi/videobridge/jvb.conf on the new server:

videobridge {
  apis {
    xmpp-client {
      configs {
        shard {
          hostname = "10.0.1.10"
          domain = "auth.meet.example.com"
          username = "jvb"
          password = "PASSWORD_FROM_MAIN_SERVER"
          muc_jids = "JvbBrewery@internal.auth.meet.example.com"
          muc_nickname = "jvb-2"
          disable_certificate_verification = true
        }
      }
    }
  }
}

ice4j {
  harvest {
    mapping {
      static-mappings = [
        {
          local-address = "10.0.1.30"
          public-address = "203.0.113.30"
        }
      ]
    }
  }
}
  • hostname is the main server's private IP.
  • muc_nickname must be unique per bridge. Two bridges with the same nickname fight over one slot in the brewery room. For bridges started automatically, generate it at boot, for example from the instance ID.
  • disable_certificate_verification is acceptable because the bridge reaches Prosody over a private network with a self-signed certificate. If the path crosses the internet, trust the certificate instead.
  • The static-mappings block gives this bridge its own public IP. Each bridge advertises its own address.

The old sip-communicator.properties names

Older guides, ours included, set these values in /etc/jitsi/videobridge/sip-communicator.properties. Current videobridge releases read jvb.conf instead, and the mapping is direct:

Old propertyWhere it lives now
org.jitsi.videobridge.xmpp.user.shard.MUC_JIDSmuc_jids in the shard block above
org.jitsi.videobridge.xmpp.user.shard.HOSTNAMEhostname in the shard block
org.jitsi.videobridge.xmpp.user.shard.MUC_NICKNAMEmuc_nickname in the shard block
org.jitsi.videobridge.ENABLE_STATISTICSvideobridge.stats.enabled

A properties file left behind on an upgraded server is ignored for these settings, which is why editing it looks like it does nothing. Statistics matter here beyond monitoring: Jicofo places conferences using what the bridges report, so leave them enabled.

sudo systemctl restart jitsi-videobridge2
sudo tail -f /var/log/jitsi/jvb.log

On the main server, /var/log/jitsi/jicofo.log should report the new bridge shortly after. If it doesn't, the brewery JID or credentials disagree; fixing Jicofo configuration errors goes through each value.

How Jicofo picks a Jitsi videobridge

Each bridge periodically reports statistics, including a stress level, into the brewery room. Jicofo uses them to place conferences. The strategy is configurable in /etc/jitsi/jicofo/jicofo.conf:

Strategy Behaviour
SingleBridgeSelectionStrategyKeep each conference on one bridge, choosing the least loaded
SplitBridgeSelectionStrategyA separate bridge for each participant; for testing cascading, not production
RegionBasedBridgeSelectionStrategyPlace participants on bridges in their own region
IntraRegionBridgeSelectionStrategyUse additional bridges only when one in the region is overloaded
VisitorSelectionStrategySeparate strategies for visitors in very large meetings
jicofo {
  bridge {
    brewery-jid = "JvbBrewery@internal.auth.meet.example.com"
    selection-strategy = RegionBasedBridgeSelectionStrategy
  }
}

For bridges in one data center, leave the default. Region-based selection only makes sense when bridges run in several regions and participants connect from far apart; conferences then span bridges that relay media between them, which scaling videobridges with Octo explains.

Multiple shards with HAProxy

A shard is a complete, independent Jitsi deployment. With several shards behind one hostname, the only rule that matters is that everyone in the same room must reach the same shard. Jitsi makes that possible by adding the room name as a room parameter to its XMPP connection URLs, so HAProxy can route on it.

frontend meet
    bind *:443 ssl crt /etc/haproxy/certs/meet.example.com.pem
    mode http
    http-request set-header X-Forwarded-Proto https
    default_backend shards

backend shards
    mode http
    balance url_param room
    hash-type consistent
    option httpchk GET /about/health
    server shard1 10.0.1.10:443 check ssl verify none
    server shard2 10.0.2.10:443 check ssl verify none

balance url_param room with consistent hashing sends the same room to the same shard every time, and keeps most rooms in place when you add a shard. The HAProxy configuration manual documents both directives.

HAProxy reqadd no longer exists

The older version of this config used reqadd to set the forwarded protocol header. That directive was removed in HAProxy 2.1 along with the rest of the req* family, and a configuration still containing it does not start at all. The replacement is http-request set-header, as in the frontend above. On a Jitsi HAProxy config inherited from a 1.8-era guide, that single line is usually the only thing in the way.

All shards share the public identity

Every shard must serve the same hostname and certificate, and the same Jitsi front-end configuration, because a user can land on any of them. Keep their config.js and authentication settings in one place and deploy them identically, or users see different behaviour depending on which room they join.

The health check path above assumes an nginx endpoint that returns 200 when the shard is healthy; point it at whatever health check your shards expose, or drop it and rely on TCP checks.

Automating it

Adding bridges by hand works for a fixed load. When usage swings through the day, you want bridges to appear and disappear on their own, with running conferences drained gracefully before a bridge shuts down. Auto scaling Jitsi Meet on AWS covers that design, and our 1000-user Jitsi test shows what one shard held under real load.

Frequently Asked Questions

Does Jitsi Meet support horizontal scaling?

Yes, at two levels. Inside one shard, you add videobridges and Jicofo spreads conferences across them. Across shards, you run several complete Jitsi deployments behind HAProxy, which sends everyone in the same room to the same shard.

How does Jicofo choose a videobridge?

Bridges report their load to Jicofo through the brewery room. The bridge selection strategy in jicofo.conf decides how that is used: the default keeps a conference on one bridge and picks a lightly loaded one, while region-based and split strategies spread participants differently.

Do I still set MUC_JIDS in sip-communicator.properties?

No, that is the old properties-file format. Current videobridges read /etc/jitsi/videobridge/jvb.conf, where muc_jids, muc_nickname and the XMPP credentials sit in the shard block under apis.xmpp-client.configs.

Which port must the extra videobridge reach on the main server?

TCP 5222 on the Prosody server, which the bridge uses to log in and join the brewery room. Open it only from the bridge's private IP. Participants still reach each bridge directly on UDP 10000.

When do I need shards instead of more bridges?

When Prosody or Jicofo becomes the bottleneck rather than bridge CPU, or when you want failure isolation so one broken deployment doesn't take all meetings down. Load test first; adding bridges is simpler and solves most capacity problems.

Scaling Jitsi Beyond One Server?

Terraform-based Jitsi deployments for 50 to 2000 concurrent users, with load-balanced and auto-scaling videobridges already designed in.

See Jitsi Infrastructure as Code