datarekha

Mixture of Experts

Frontier open models are huge on paper but cheap to run, because most of their parameters sit idle on any given token. How sparse Mixture-of-Experts buys capacity at near-fixed compute.

8 min read Advanced NLP & Transformers Lesson 33 of 44

What you'll learn

  • How a router sends each token to its top-k experts instead of one dense FFN
  • Why MoE scales parameters (capacity) without scaling per-token compute
  • The load-balancing problem and why MoE training adds an auxiliary loss

Before you start

Here’s a riddle from the 2026 model landscape: a model can have hundreds of billions of parameters yet cost about the same to run as a model a fraction of its size. The trick is sparsity — on any given token, most of the model doesn’t fire. The mechanism is Mixture-of-Experts (MoE), and it’s why models like Mixtral, DeepSeek, and Qwen-MoE can be enormous on paper and still affordable to serve.

TryMixture of Experts · sparse routing

Big model, small bill — route each token to a few experts

Instead of one big feed-forward network, an MoE layer has 8 experts and a router that sends each token to its top-2. The model holds all 8 experts' parameters, but each token only pays for 2. Capacity scales with the expert count; compute scales with k.

capacity (params)
compute / token
active fraction25%
token \ expertE0E1E2E3E4E5E6E7
The
cat
sat
on
a
warm
mat
today
load31224112
8 experts, top-2 → 8× the parameters at ~2× the compute of a single expert. That's the MoE bargain: scale capacity (and knowledge) far past what a dense model could afford to run. But notice the uneven load across experts — some are overworked, others idle. Real MoE training adds an auxiliary load-balancing loss to spread tokens evenly, or the popular experts hog all the learning.

One big FFN → many small experts

Recall from the transformer block that the feed-forward (FFN) sublayer holds most of a transformer’s parameters and runs on every token. MoE replaces that single FFN with N smaller expert FFNs plus a tiny router. For each token, the router scores the experts and sends the token only to its top-k (usually k=1 or 2). The other experts are skipped entirely for that token.

So the model stores all N experts, but any single token only computes k of them. Here one token is routed through an 8-expert layer with top-2 routing — six experts never fire for it:

Top-k routing: store N experts, compute only ktokenRouterscores expertsExpert 0 · skippedExpert 1 · skippedExpert 2 ✓ activeExpert 3 · skippedExpert 4 · skippedExpert 5 ✓ activeExpert 6 · skippedExpert 7 · skippedΣlayer outputcapacity ∝ N stored expertscost ∝ k = 2 computed
All eight experts live in memory, but the router fires only two per token — so parameters (capacity) grow with N while compute (cost) grows only with k.

The bargain: capacity scales with N, compute with k

That’s the whole point, stated as a tradeoff:

  • Parameters (capacity, “knowledge”) grow with the number of experts N.
  • Compute per token (FLOPs, cost) grows only with k, the experts actually used.

A model with 8 experts and top-2 routing has roughly the parameter count of 8 FFNs but the per-token compute of 2. You get a much larger, more capable model without paying to run all of it on every token. This is why “total parameters” and “active parameters” are now reported separately — a model might be “236B total, 21B active.”

The catch: load balancing

A naive router has a failure mode: it learns to love a few experts and send everything to them, while other experts get no tokens, no gradient, and never learn. That wastes most of the model’s capacity — the per-expert load ends up wildly uneven.

The standard fix is an auxiliary load-balancing loss added during training that penalizes imbalance, nudging the router to spread tokens evenly across experts. Here’s the imbalance, made concrete:

import numpy as np

rng = np.random.default_rng(1)
n_experts, n_tokens, k = 8, 2000, 2

# A biased router: experts 0-1 are over-preferred (the failure mode).
bias = np.array([3.0, 2.5] + [0.0]*(n_experts-2))
load = np.zeros(n_experts, dtype=int)
for _ in range(n_tokens):
    scores = rng.standard_normal(n_experts) + bias
    topk = np.argpartition(scores, -k)[-k:]      # pick top-k experts
    load[topk] += 1

ideal = n_tokens * k / n_experts
print("tokens routed to each expert:", load.tolist())
print(f"ideal (balanced) per expert: {ideal:.0f}")
print(f"busiest/idle ratio: {load.max() / max(load.min(),1):.1f}x  "
      f"-> needs a load-balancing loss")
tokens routed to each expert: [1876, 1713, 64, 75, 63, 71, 62, 76]
ideal (balanced) per expert: 500
busiest/idle ratio: 30.3x  -> needs a load-balancing loss

The two favoured experts swallow ~3,600 of the 4,000 routed slots while the other six starve — a 30× imbalance. The auxiliary loss is what pushes those bars back toward the ideal of 500 each, so every expert sees enough tokens to actually learn.

In one breath

  • Mixture-of-Experts replaces the single dense FFN with N smaller expert FFNs plus a tiny router that sends each token to only its top-k (usually 1–2).
  • The bargain: capacity (parameters) scales with N, compute (FLOPs) scales only with k — which is why models now report “236B total, 21B active.”
  • It saves compute, not memory: all N experts still sit in VRAM, so the serving bottleneck shifts from FLOPs to memory and to networking tokens to the right expert.
  • A naive router collapses onto a few favourite experts (a 30× load imbalance in the demo), starving the rest — so MoE training adds an auxiliary load-balancing loss to spread tokens evenly. This economics is why most 2026 frontier/open models (Mixtral, DeepSeek, Qwen-MoE) are sparse.

Quick check

Quick check

0/3
Q1In a Mixture-of-Experts layer, what does the router do?
Q2What is the core tradeoff MoE exploits?
Q3Why do MoE models add an auxiliary load-balancing loss during training?

Next

That completes the Deep Learning track’s modern-architecture arc. From here, the Generative AI track takes these building blocks into production — serving, RAG, reasoning models, and evaluation.

Sign in to track your progress

Completed lessons, your XP, level, and streak save to your account — it's free and takes a few seconds.

Practice this in an interview

All questions
What is Mixture of Experts (MoE) and how does it improve LLM scalability?

MoE replaces a dense feed-forward layer with many expert subnetworks plus a gating router that activates only a few experts per token. This grows total parameter count and capacity while keeping per-token compute roughly constant, since only a sparse subset of experts runs for any given token.

How would you reduce the cost of serving an ML or LLM model in production without hurting quality?

Work top-down: start at the model layer with quantization, distillation, or routing cheaper models for easy requests, since model choices drive every downstream cost. Then optimize the runtime with batching, caching, and techniques like prompt caching for LLMs, and finally match infrastructure to the load using autoscaling on queue depth and spot or batch capacity. Track cost per token or per prediction alongside latency percentiles and accuracy so optimizations never silently degrade quality.

Why are smaller language models (SLMs) sometimes preferable to larger ones?

Smaller models win on latency, inference cost, on-device deployment, and fine-tuning feasibility. When trained on high-quality, curated data and aligned for a narrow task, a 7B–13B model can match or exceed a general-purpose 70B+ model on that specific workload while using a fraction of the compute budget.

What techniques reduce LLM cost and latency in production?

Cost scales with input plus output tokens; latency scales with output tokens and model size. The highest-leverage levers are: model routing (use a small model when the task is simple), prompt caching (reuse expensive prefix computation), output length control, and batching. Together these can cut spend 60–90% without quality regression.

Related lessons

Explore further

Skip to content