The one-line answer
Rating a 1v1 game and you want it simple and transparent? elo.
Rating a 1v1 game where players play infrequently and you care about accuracy? glicko.
Rating anything else — free-for-alls, teams, any count above two? trueskill. It is the only built-in that fits.
Whichever you pick, it is fixed for the pool that stores it. Recording a result is one call, rating and ranking together is the worked example, and every option is in the reference.
The table
| Algorithm | Players | Teams | Skill number |
|---|---|---|---|
elo | 2 | no | The rating itself |
glicko | 2 | no | rating − 2·RD |
trueskill | 2+ | yes | μ − 3·σ |
elo
One number per player, and nothing else. A win moves both players by K × (actual − expected), where the expected score comes from the rating gap.
Beating a stronger player earns more than beating a weaker one. That is the whole model.
K is the single dial — default 32. Larger reacts faster and swings harder; smaller is steadier.
Elo has no notion of uncertainty, so a brand-new player and a veteran with a thousand games are treated identically at the same rating. The new player’s number just takes many games to find its level.
Reach for it when you want a rating players can understand at a glance.
glicko (Glicko-2)
Elo’s successor, still 1v1. Alongside the rating it tracks a rating deviation — how confident the system is — and a volatility — how erratic the player’s recent results have been.
A result from a high-deviation player moves their rating a lot and their opponent’s a little. Deviation shrinks as they play and grows back while they are idle.
Which is why Glicko re-converges fast for infrequent players: a returning player is treated as uncertain and finds their level in a handful of games rather than dozens.
The volatility is solved each game by an iteration — the crux of Glicko-2 — constrained by the system constant τ, default 0.5. Smaller damps volatility swings.
The exposed skill number is rating − 2·RD — a conservative estimate that treats an uncertain player as weaker until they have proven otherwise, which keeps new and returning players out of lopsided matches.
trueskill
The Bayesian one, and the only built-in that rates more than two players.
Each player is a Gaussian belief — a mean skill μ and an uncertainty σ. A game is evidence that shifts every participant’s belief: winners’ mean rises, losers’ falls, and everyone’s uncertainty shrinks toward certainty.
It handles 1v1, N-player free-for-alls (each player a team of one), and teams — where a team’s skill is the sum of its members’ and the result is distributed back across them.
Constants:
β | Skill class width. How much a single game can prove. Default σ0/2 |
τ | Dynamics. Lets ratings drift so a long-dormant player is not frozen. Default σ0/100 |
| Draw probability | Shapes how a tie is interpreted |
Matchmaking buckets on μ − 3·σ — a conservative rank that stays low until the system is confident.
For more than two teams this uses the standard sequential approximation.
Everything is validated at assembly
Not at the first recorded result.
An unknown algorithm id, a roster the algorithm cannot rate, a team format on an algorithm with no team model, or params the algorithm refuses — all fail on deploy.
The same way a bad game config fails on deploy rather than at 3am.
The choice is immutable in practice
Registering your own
Declare an id, a params schema with defaults, a state schema, the player counts you support, and pure initial, update and skill functions.
Register it in your Worker entry before the capability assembles, then name its id in a game.
Your params and player bounds are validated exactly as the built-ins are.