Chapter 13 · Section 13.3 · 55 min

Load balancing

Train an MoE layer with nothing but the language-modeling loss and watch the router. For a few dozen steps the tokens spread out over the experts. Then one expert pulls ahead by a little, by luck of initialization, so it receives a few more tokens, so it trains a little more, so it gets a little better, so the router sends it even more. A few dozen steps later it handles almost everything, and the other experts sit idle. You have paid for eight experts and you are training one.

This is expert collapse, and it follows directly from the router gradient of §13.2, which only rewards experts the router already chose. This section explains why it happens, derives the auxiliary loss that the Switch Transformer used to prevent it and proves where that loss is minimized, adds the router z-loss that keeps logits from blowing up, builds the auxiliary-loss-free bias method of DeepSeek-V3, and ends with what to monitor during a real run.

Why routers collapse

Recall the router gradient for one token with chosen set K\mathcal{K}, gates gig_i, and ai=∂L/∂gia_i = \partial\mathcal{L}/\partial g_i,

∂L∂rj=gj(aj−∑i∈Kgiai)  for j∈K,0 otherwise.\frac{\partial\mathcal{L}}{\partial r_j} = g_j\Big(a_j - \sum_{i\in\mathcal{K}} g_i a_i\Big) \ \text{ for } j \in\mathcal{K}, \qquad 0 \text{ otherwise}.

Two facts combine into a feedback loop. An expert that is chosen more often receives more gradient updates, so it improves faster and its outputs become more useful, which makes −aj-a_j larger and pushes its logit up. And an expert that is never chosen receives no router gradient at all, so nothing in the task loss can ever tell the router it would have been useful. Rich experts get richer, and poor ones never get a chance. Shazeer et al. (2017) observed exactly this, a gating network that converges to large weights for the same few experts, an imbalance that reinforces itself, and the DeepSeek-V3 report calls the end state routing collapse.

Collapse costs more than wasted parameters. A collapsed expert overflows its capacity, so tokens are dropped (§13.2). In expert-parallel training, the GPU holding it does most of the work while the others wait (§13.4). And the model degenerates toward a dense model the size of one expert, with all the machinery of an MoE and none of the benefit.

Play with the simulation below before reading on. It trains a toy router whose experts improve with the tokens they receive, which is the feedback loop above in miniature, and lets you compare three ways of fighting it.

Does the router collapse onto a few experts, and what stops it?
8 experts, top-2, 128 tokens per step. Experts improve with the tokens they train on, so popular experts become more attractive. Top, each expert's share of tokens over 240 steps. Bottom, MaxVio for all three methods.
Loading interactive figure…

In the toy, a small auxiliary loss only delays the collapse, because the task signal is strong, and a larger coefficient is needed. Bias balancing keeps the load even from the start, as long as its step γ\gamma is large enough to keep up with the pull, and it does so without the router's weights ever being pushed toward balance, which is the property DeepSeek wanted. We will see both reasons in the math.

The Switch auxiliary loss

Fedus et al. (2022) add a single term to the loss, for a batch of TT tokens routed among EE experts,

Laux=α E∑i=1Efi Pi,fi=1kT∑t=1T1[i∈Kt],Pi=1T∑t=1Tpt,i,\mathcal{L}_{\text{aux}} = \alpha\, E \sum_{i=1}^{E} f_i\, P_i, \qquad f_i = \frac{1}{kT}\sum_{t=1}^{T}\mathbb{1}\big[i \in \mathcal{K}_t\big], \qquad P_i = \frac{1}{T}\sum_{t=1}^{T} p_{t,i},

where pt=softmax⁡(rt)\mathbf{p}_t = \operatorname{softmax}(\mathbf{r}_t) is the router's full softmax over all EE experts, fif_i is the fraction of token assignments that went to expert ii (the Switch paper has k=1k = 1, and dividing by kk makes ∑ifi=1\sum_i f_i = 1 for any kk), PiP_i is the average probability the router gave expert ii, and α\alpha is a small coefficient, 10−210^{-2} in Switch and ST-MoE. In plain words, multiply each expert's share of the work by its share of the router's belief, and add those up.

The two factors play different roles. The count fif_i is a step function of the logits, so its gradient is zero almost everywhere, and the loss treats it as a constant. All of the gradient flows through PiP_i, which is smooth. That is the trick. The non-differentiable thing we want to balance (the actual load) sets the weights, and the differentiable proxy (the probabilities) is what moves.

Where the loss is minimized

Start with the value at perfect balance. If every expert gets fi=1/Ef_i = 1/E and the router's average probabilities are also uniform, Pi=1/EP_i = 1/E, then

Laux=αE⋅E⋅1E⋅1E=α.\mathcal{L}_{\text{aux}} = \alpha E \cdot E\cdot\frac1E\cdot\frac1E = \alpha .

The factor EE in front is there so this value does not depend on the number of experts. At full collapse with k=1k = 1, every token goes to expert 1 with probability near 1, so f1=P1=1f_1 = P_1 = 1 and the loss is αE\alpha E. With top-kk collapsed onto kk experts that share the probability evenly, fi=Pi=1/kf_i = P_i = 1/k on those kk, and the loss is αEk/k2=αE/k\alpha E k/k^2 = \alpha E/k.

Why is uniform the minimum? Look at the loss in the regime it is designed for, where the router's probabilities match its actual routing, Pi=fiP_i = f_i. Then Laux=αE∑ifi2\mathcal{L}_{\text{aux}} = \alpha E\sum_i f_i^2, and with ∑ifi=1\sum_i f_i = 1, the Cauchy-Schwarz inequality gives

1=(∑i=1E1⋅fi)2≤(∑i=1E12)(∑i=1Efi2)=E∑i=1Efi2,soLaux≥α,1 = \Big(\sum_{i=1}^{E} 1\cdot f_i\Big)^2 \le \Big(\sum_{i=1}^{E} 1^2\Big)\Big(\sum_{i=1}^{E} f_i^2\Big) = E\sum_{i=1}^{E} f_i^2, \qquad\text{so}\qquad \mathcal{L}_{\text{aux}} \ge \alpha,

with equality exactly when all fif_i are equal. In plain words, the sum of squared shares is smallest when the shares are equal, so the loss bottoms out at uniform routing and grows as load concentrates.

The gradient tells you how it gets there. Differentiate through PiP_i only, using the softmax Jacobian ∂pt,i/∂rt,j=pt,i(δij−pt,j)\partial p_{t,i}/\partial r_{t,j} = p_{t,i}(\delta_{ij} - p_{t,j}),

∂Laux∂rt,j=αET∑ifi pt,i(δij−pt,j)=αET pt,j(fj−∑ifi pt,i).\frac{\partial\mathcal{L}_{\text{aux}}}{\partial r_{t,j}} = \frac{\alpha E}{T}\sum_i f_i\, p_{t,i}(\delta_{ij} - p_{t,j}) = \frac{\alpha E}{T}\, p_{t,j}\Big(f_j - \sum_i f_i\, p_{t,i}\Big).

In plain words, for every token, the loss lowers the logit of each expert whose load is above the token's probability-weighted average load and raises the logits of experts whose load is below it, in proportion to how much probability the token gave them. Overloaded experts become less attractive to every token at once.

∂ The minimum is uniform only in the intended regime

The Cauchy-Schwarz argument assumed Pi=fiP_i = f_i. Over all logits, ∑ifiPi\sum_i f_iP_i can dip below 1/E1/E. Take E=2E = 2, k=1k = 1, and three tokens. Two have probabilities (0.51,0.49)(0.51, 0.49) and are routed to expert 1. One has (0,1)(0, 1) and is routed to expert 2. Then f=(2/3,1/3)f = (2/3, 1/3), P=(0.34,0.66)P = (0.34, 0.66), and

E∑ifiPi=2(23⋅0.34+13⋅0.66)=0.893<1.E\sum_i f_iP_i = 2\Big(\tfrac23\cdot0.34 + \tfrac13\cdot0.66\Big) = 0.893 < 1 .

The loss is lowered here by giving expert 2 high probability on the tokens it gets and near-ties on the tokens it does not, while expert 1 does more work. This loophole is narrow (it needs near-ties, which are fragile because tiny logit changes flip the routing and with it ff), and in practice the loss behaves as the Cauchy-Schwarz argument says. But it is the honest statement of the theorem, and it is a good answer when an interviewer asks whether the loss is "minimized at uniform routing".

Python · cell 1

Older losses have the same goal. Shazeer et al. (2017) penalized the squared coefficient of variation of each expert's total gate weight (its importance), plus a smooth estimate of its load built from the noisy gating's normal CDF. GShard's loss is 1E∑eceSme\frac1E\sum_e \frac{c_e}{S}m_e, where ce/Sc_e/S is the fraction of the group's SS tokens whose first choice is expert ee and mem_e is its mean gate, so up to the coefficient it is the Switch loss divided by E2E^2. DeepSeek writes fif_i scaled by E/(kT)E/(kT) so that it equals 1 at balance, which moves the factor EE inside ff and leaves the loss unchanged.

Interview

The Switch load-balancing loss

Implement switch_aux_loss(R, idx, alpha) for router logits R of shape (T, E) and the chosen experts idx of shape (T, k). Compute pt=softmax⁡(rt)\mathbf{p}_t = \operatorname{softmax}(\mathbf{r}_t) over all experts, fif_i as the fraction of the kTkT assignments that went to expert ii, PiP_i as the mean of pt,ip_{t,i} over tokens, and return αE∑ifiPi\alpha E\sum_i f_iP_i as a float. The tests check the values at uniform and collapsed routing and catch the usual normalization mistakes.

Hidden tests, hints, and AI help, from $1.99 a month.

How large should α\alpha be? Too small and collapse wins, as in the widget. Too large and the balancing gradient fights the language-modeling gradient on every token, which costs quality. Switch swept α\alpha from 10−110^{-1} to 10−510^{-5} and chose 10−210^{-2} as large enough to balance without overwhelming the main loss. That tension, a hyperparameter whose right value depends on the run, is what motivated the bias method below.

The router z-loss

Balancing fixes where tokens go. A second failure is about how confident the router is. Router logits tend to grow during training, and large logits are dangerous in low precision. A bfloat16 number has 8 significant bits (§8.5), so near 100 consecutive representable values are 0.5 apart, and near 1,000 they are 4 apart. Two experts whose logits differ by 0.3 become a tie, or a gap of 0.5, depending on rounding. The exponentials inside the softmax amplify such roundoff, and Zoph et al. (2022) found that this was a source of training instability in large MoE models.

Python · cell 2

The probabilities depend only on the gaps between logits, yet at height 1,000 bfloat16 has erased the gaps entirely. ST-MoE's fix is the router z-loss,

Lz=αzT∑t=1T(log⁡∑j=1Eert,j)2=αzT∑t=1Tlse⁡(rt)2,\mathcal{L}_z = \frac{\alpha_z}{T}\sum_{t=1}^{T}\Big(\log\sum_{j=1}^{E} e^{r_{t,j}}\Big)^2 = \frac{\alpha_z}{T}\sum_{t=1}^{T}\operatorname{lse}(\mathbf{r}_t)^2,

with αz=10−3\alpha_z = 10^{-3}, the value Zoph et al. chose by a sweep. In plain words, penalize the size of each token's log-partition function, which keeps the logits near zero. It is the same leash that PaLM's z-loss puts on the output softmax (§8.8), applied to the router.

Why the log-sum-exp and not the logits themselves? Because adding a constant cc to all of a token's logits leaves the softmax unchanged but shifts lse⁡\operatorname{lse} by exactly cc. So the z-loss can pull the overall level of the logits toward zero without touching the routing. It also penalizes a large spread, since lse⁡(r)≥max⁡jrj\operatorname{lse}(\mathbf{r}) \ge \max_j r_j. For example, logits (10,9,8,0)(10, 9, 8, 0) have lse⁡=10.41\operatorname{lse} = 10.41 and a squared value of 108.3, while the same logits shifted down by 8, (2,1,0,−8)(2, 1, 0, -8), route identically with lse⁡=2.41\operatorname{lse} = 2.41 and a squared value of 5.8. The gradient is simple,

∂Lz∂rt,j=2αzT lse⁡(rt)  pt,j,\frac{\partial\mathcal{L}_z}{\partial r_{t,j}} = \frac{2\alpha_z}{T}\,\operatorname{lse}(\mathbf{r}_t)\; p_{t,j},

because ∂lse⁡/∂rj=pj\partial\operatorname{lse}/\partial r_j = p_j. Each logit is pushed down in proportion to its probability and to how large the partition function is. In ST-MoE's stability study, the z-loss made all three runs stable and slightly improved quality, where alternatives such as update clipping also stabilized training but badly hurt quality.

Interview

The router z-loss and its gradient

Implement router_z_loss(R, alpha_z) for logits R of shape (T, E). Return (loss, grad), where loss is αzT∑tlse⁡(rt)2\frac{\alpha_z}{T}\sum_t\operatorname{lse}(\mathbf{r}_t)^2 as a float and grad of shape (T, E) is its derivative with respect to R. Both must be finite for logits in the thousands.

Hidden tests, hints, and AI help, from $1.99 a month.

Balancing without a loss

Every auxiliary loss has the same weakness. Its gradient flows into the router weights, the same weights that the language-modeling loss is training, and on every token the two gradients disagree to some degree. Wang et al. (2024) call this interference. A large α\alpha balances well and hurts perplexity, and a small one hurts less and balances badly.

Their alternative changes the routing decision without changing the gradient. Give every expert a bias bib_i that is added to its score only for choosing the top kk, not for the gate, and adjust the biases by a fixed rule after each step. In DeepSeek-V3's form, with sigmoid affinities st,i=σ(rt,i)s_{t,i} = \sigma(r_{t,i}),

Kt=TopK⁡({st,i+bi}i=1E, k),gt,i=st,i∑j∈Ktst,j  for i∈Kt,\mathcal{K}_t = \operatorname{TopK}\big(\{s_{t,i} + b_i\}_{i=1}^{E},\ k\big), \qquad g_{t,i} = \frac{s_{t,i}}{\sum_{j\in\mathcal{K}_t} s_{t,j}} \ \text{ for } i\in\mathcal{K}_t,

and after each training step, with cic_i the number of tokens expert ii received and cˉ\bar c the mean over experts,

bi←bi+γ sign⁡(cˉ−ci).b_i \leftarrow b_i + \gamma\,\operatorname{sign}\big(\bar c - c_i\big).

In plain words, an overloaded expert's bias goes down by γ\gamma and an underloaded expert's goes up by γ\gamma, which nudges the next batch's selections toward balance, while the gates, and therefore the gradients, still come from the unbiased scores.

The bias is not a parameter of the model in the gradient sense. Nothing backpropagates into it, so balancing creates no interference with the main loss. It acts like a price in a market. Busy experts get more expensive and idle ones cheaper until supply and demand match. DeepSeek-V3 used γ=0.001\gamma = 0.001 for the first 14.3T training tokens and γ=0\gamma = 0 for the last 500B, and reports dropping no tokens at all, in training or inference.

The evidence is quantitative. Wang et al. trained 1B and 3B MoE models with 64 routed experts, 2 shared, and 6 active, and measured imbalance with MaxVio⁡=(max⁡ici−cˉ)/cˉ\operatorname{MaxVio} = (\max_i c_i - \bar c)/\bar c, how far the busiest expert is above the fair share. With the auxiliary loss, the 1B model reached perplexity 9.56 with a MaxVio of 0.72 over the validation set. Bias balancing reached 9.50 with a MaxVio of 0.04. At 3B the numbers were 7.97 and 0.52 versus 7.92 and 0.04. Better balance and better perplexity at once is the signature of removing interference. DeepSeek-V3's own ablations, at 15.7B and 228.7B total parameters, show the auxiliary-loss-free model ahead on most benchmarks, though not all (at the larger size its MMLU was 67.2 against 68.3).

DeepSeek-V3 does keep one tiny auxiliary loss, a sequence-wise balance term with α=10−4\alpha = 10^{-4}, to stop any single sequence from piling onto a few experts. The paper also compares where balance is enforced. Requiring balance within every sequence is stricter than requiring it over a whole batch, and it fights specialization (a sequence of code should be allowed to use the code-heavy experts). In their 1B ablation, a sequence-wise auxiliary loss reached validation loss 2.258, while bias balancing and a batch-wise auxiliary loss both reached 2.253, and the bias-balanced model showed clearer domain specialization of experts.

The same question hides inside every ordinary auxiliary loss. Frameworks usually compute fif_i and PiP_i within each micro-batch on each GPU, and a micro-batch of a few long sequences is close to the strict sequence-wise case. Qiu et al. (2025) synchronized the counts fif_i across all data-parallel ranks, so that the loss balances the global batch instead, and reported lower perplexity and more domain-specialized experts at no extra communication worth mentioning (one vector of EE numbers per layer).

Interview

Auxiliary-loss-free routing and the bias update

Implement bias_route_and_update(S, b, k, gamma) for affinities S of shape (T, E) (already passed through a sigmoid) and biases b of shape (E,). Choose each token's k experts by the largest S + b (ties to the smaller index), compute gates from the unbiased S normalized over the chosen experts, count each expert's tokens, and update the biases with bi←bi+γsign⁡(cˉ−ci)b_i \leftarrow b_i + \gamma\operatorname{sign}(\bar c - c_i). Return (idx, gates, new_b) with shapes (T, k), (T, k), (E,). Do not modify b in place.

Hidden tests, hints, and AI help, from $1.99 a month.

Expert collapse, and its cousins

"Collapse" covers a few related failures, and it helps to name them separately.

  • Load collapse. A few experts take most tokens, as above. Balancing losses and biases are the cure.
  • Dead experts. An expert that stops being chosen gets no gradient, its weights freeze, and it can never recover through the task loss alone. A balancing mechanism is the only thing that brings it back, by raising its score until it is tried again.
  • Representation collapse. Chi et al. (2022) argue that the router's training pulls token representations toward clusters around the experts' router vectors (the columns of Wr\mathbf{W}_r), which reduces what the representation can express. Their fix scores tokens against experts on a low-dimensional hypersphere.
  • Redundant experts. Experts are all used but learn nearly the same function, which wastes capacity without any imbalance. This is one motivation for the shared experts of DeepSeekMoE (§13.5), which take the common knowledge so routed experts do not each have to store it.

Several training choices help prevent collapse before balancing has to. Switch initializes weights with one tenth of the usual scale, and computes the router in float32 even when the rest of the model runs in bfloat16 (§13.6). A router whose logits start near zero routes almost uniformly at first, which gives every expert some tokens and some gradient.

Monitoring expert usage

In a real run you watch routing the way you watch the loss. These are the numbers worth logging per MoE layer, over a window of steps.

metricdefinitionhealthywarning sign
load fractionsfif_i, share of assignments per expertall near 1/E1/Eone expert above 2/E2/E, or some near 0
MaxVio(max⁡ici−cˉ)/cˉ(\max_i c_i - \bar c)/\bar cbelow about 0.1 to 0.3growing, or above 1
load entropyH(f)/log⁡EH(\mathbf{f})/\log Enear 1falling over training
drop ratedropped assignments / kTkTunder 1%rising, which means CF is too small or balance is poor
router entropymean over tokens of H(pt)H(\mathbf{p}_t)well below log⁡E\log E but not 0near log⁡E\log E (router has not learned) or near 0 (overconfident)
z-loss, max logitlse⁡2\operatorname{lse}^2 and max⁡t,jrt,j\max_{t,j} r_{t,j}stable or slowly growingsteady growth, which precedes instability
dead expertsexperts with fi<0.1/Ef_i < 0.1/E over a windownoneany

The load entropy H(f)=−∑ifilog⁡fiH(\mathbf{f}) = -\sum_i f_i\log f_i divided by log⁡E\log E is 1 for perfect balance and 0 for total collapse. Different layers often behave differently, so log per layer, not just an average. And measure on held-out data too, since routing on a validation set can differ from routing on the training stream (Wang et al. report MaxVio both ways).

Core

Routing statistics for a training dashboard

Implement routing_stats(idx, E, cap) for chosen experts idx of shape (T, k), the number of experts E, and a capacity cap per expert. Return a dict with load (shape (E,), the fraction fif_i of the kTkT assignments per expert), maxvio (computed from the counts cic_i), entropy (the normalized load entropy H(f)/log⁡EH(\mathbf{f})/\log E, treating 0log⁡00\log0 as 0), and drop (the fraction of assignments beyond capacity, ∑imax⁡(0,ci−cap⁡)/(kT)\sum_i\max(0, c_i - \operatorname{cap})/(kT)).

Hidden tests, hints, and AI help, from $1.99 a month.

In PyTorch

In PyTorch the auxiliary loss is three lines, and autograd confirms the gradient we derived, flowing only through PiP_i because fif_i comes from integer counts. The z-loss uses torch.logsumexp, which is stable.

🔥 In PyTorchfor a machine with PyTorch
methodhow it balancesgradient interferenceknobdropsused by
importance and load lossesCV² of gate mass and smoothed loadyestwo weightsyesShazeer 2017
Switch auxiliary lossαE∑ifiPi\alpha E\sum_i f_iP_iyes, grows with α\alphaα≈10−2\alpha \approx 10^{-2}with capacitySwitch, GShard (scaled), OLMoE
router z-losskeeps logits small, not balancesmallαz≈10−3\alpha_z \approx 10^{-3}n/aST-MoE, OLMoE
expert choiceexperts pick tokensnonecapacitysome tokens get no expertZhou 2022
bias balancingper-expert bias on selection onlynonestep γ≈10−3\gamma \approx 10^{-3}none reportedWang 2024, DeepSeek-V3

Read more

Watch next

🎬 Mixture of Experts (MoE), Visually Explained · Jia-Bin Huang · starts at 17:26The auxiliary load-balancing loss, its simplified form, and auxiliary-loss-free balancing, visualized.
🎬 Switch Transformers: Scaling to Trillion Parameter Models with Simple and Efficient Sparsity · Yannic KilcherA paper reading of Switch, including the auxiliary loss, the capacity factor, and selective precision.