Luke Angel
A row of eight circles — five dimmed, three filled in dark green — with a curved arrow looping back from end to start, suggesting a queue that refills when empty.

Picking Speakers Without Picking Favorites

by
#facilitation#meetings#oncall#team-management#rotation#fairness

A row of eight circles — five dimmed, three filled in dark green — with a curved arrow looping back from end to start, suggesting a queue that refills when empty.

A friend runs an eight-person engineering team. The same two engineers spoke in every standup. The same one volunteered for every oncall shift. The same three ran every demo. He'd noticed, mentioned it twice in retros, the team agreed it was a problem — and nothing changed. He asked me if I'd build him "something dumb, like a wheel-spin thing" to take the picking out of his hands.

I built it. The whole project is called Fate Games and the picker at its heart is the Wheel of Death. The tagline is "No volunteers needed." If that sounds harsher than the problem it solves, keep reading — the framing turns out to be load-bearing, in the opposite direction you'd expect.

The thing that doesn't work: "let's be more inclusive"

The "soft" fix — say in the retro that everyone should speak more, ask quieter people directly — works for one or two meetings and then drifts back. It drifts back because the underlying selection mechanism hasn't changed. Whoever speaks first still wins. Whoever's top-of-mind for the lead still gets the work. Over weeks the gap compounds.

The harder fix is to take the human out of the picking for the picks that should rotate fairly. Standup report-outs. Oncall shifts. Who runs the demo. Who facilitates retro. None of those needs a manager's judgment call — they need a rotation that doesn't forget anyone.

That's a one-page app. I built it in an afternoon. Then I spent another afternoon getting the fairness mechanism right, because the obvious implementation is wrong in a way that's hard to see until you do the math.

Pure random isn't fair

When you read "random," your gut reaches for Math.random() * users.length. That picks a person, independently, every spin.

That's wrong for this use case.

In an 8-person group, pure random across 8 spins:

  • The probability that everyone gets picked once is 8! / 8^80.24%.
  • The probability that at least one person is skipped is therefore ≈ 99.76%.
  • The expected number of distinct people picked is 8 · (1 - (7/8)^8)5.27.

That last number is the one I keep coming back to. With pure random, you'd expect about three of your eight people to not have spoken at all after a week of daily standups, while one or two have gone twice. That's not "fair with some variance" — that's worse than the manager's habits, because the manager at least notices that Eddie hasn't reported in a week. The dice don't.

A second-order problem makes it actually worse: streaks feel personal. The person who gets picked three times in a row stops trusting the wheel. The person who hasn't been picked in two weeks stops paying attention to standup. The mechanism that was supposed to take the favoritism out of the picking creates a new, less defensible flavor of it.

The fix: a depleting pool

The mechanism that actually works is a queue that empties:

  1. Start with all N people in the pool.
  2. On each spin, pick uniformly at random from the pool (not from the full group).
  3. Remove the picked person from the pool.
  4. When the pool is empty, refill it.

Properties:

  • Guaranteed coverage. Every N spins, everyone has gone exactly once. No skips, no doubles, no compounding gaps.
  • Still random within the round. The order inside each round of N is unpredictable, so it doesn't feel like a deterministic rota.
  • Self-correcting after team changes. Add a person mid-week; they show up in the next pool refill. Remove a person; the pool shrinks. No special-case logic.

This is the same shape as a card deck that gets shuffled and dealt down, then reshuffled when empty. Programmers know this as a Fisher-Yates draw without replacement. Statisticians call it sampling without replacement, with repeated rounds. Kids dividing teams on a playground call it "everyone goes before anyone goes again."

In code it's maybe twenty lines. The version in Fate Games stores the pool in localStorage per {teamId}:challenge:{challengeId} so the same team can have a separate rotation for standup, oncall, and demo-running, each with its own depleting state. When the pool empties, the next spin reseeds from the full team.

That's the whole algorithm. The hard part isn't the math — it's making sure the user feels like the wheel is fair while the wheel does its work.

The Wheel of Death — and why the snark is the product

This is where Fate Games diverges from every "team picker" tool I'd looked at while building it. The polite ones — "team randomizer," "fair rotation widget," "spinning wheel" — all reassure you that being picked is fine, that the algorithm is fair, that nothing personal is happening. They are all read by users as exactly what they are: managerial tools designed to soften an awkward moment.

The thing my friend's team was actually doing in standup wasn't avoiding speaking. It was being polite about whose turn it was. "Oh, you go," "no you go," "no really, I went last time" — that's the loop the wheel had to break. The polite framing was the thing keeping the same two people speaking every day, because the polite framing made being picked feel like being chosen against you.

So I went the other way. The picker is the Wheel of Death. It glows orange, makes a satisfying clack, and lands on you with a skull-and-crossbones celebration. When you get picked, the headline doesn't say "You've been selected to share an update" — it says "Spin to die!"

The Wheel of Death mid-spin in Fate Games — a vibrant eight-segment color wheel with the team's emoji avatars around the rim, glowing yellow LED dots along the edge, pointed at by a yellow indicator triangle at the top.

It feels worse than "team randomizer." It works better. Two reasons:

One — humor lowers the social cost of being picked. When the wheel says "Spin to die!" and lands on you with a skull, you have a script. You laugh. You go. The polite framing leaves you with no script except "uh, I guess it's me?" — which is the exact pause the room used to fill with "no no no, you go." The snark turns the moment into a bit, and the bit doesn't need consensus.

Two — being picked stops being a status thing. A team-randomizer that tries to be respectful implicitly says "being picked is an honor / responsibility / promotion." Wheel of Death says "you got eaten by a T-Rex" (one of the other games is literally called T-Rex Pit). The picker doesn't claim it's fair-in-a-noble-sense; it claims it's fair-in-a-doesn't-care sense. Quieter people I'd shown this to read that as a relief — the picker doesn't think being picked is a big deal, so they don't have to either.

The result reveal after a Wheel of Death spin: a large skull emoji over the picked person's name in coral red — 'Eddie Bloom' — with bone-and-skull confetti animations falling around it.

The "no volunteers needed" tagline is the same move. It's not telling users that volunteering is bad. It's reassuring them that they don't have to perform willingness. That performance is what the polite framing was extracting from them every standup.

Make the rotation auditable

The depleting pool is invisible to the user mid-spin — they see a wheel, they see a name, they see a skull. Over a week of standups, the question stops being "is this spin fair?" and starts being "am I being picked more than my share?" That deserves a real answer, not a vibe.

The Leaderboards page keeps a running count per person across all rotations they're in:

Leaderboards page in Fate Games — a 'Most Picked' tab showing the top of the rank table: Max Kowalski at 20 picks with a 'Veteran' badge, Fiona Drake at 11 with 'Regular', Priya Sharma at 11 with 'Regular', a long tail with 'Rookie' badges, and filter dropdowns for Team, Challenge, and Game at the top.

Two things land in this view that I didn't plan and ended up keeping:

  • Gamification titles — Fresh Meat (0 picks), Rookie (1+), Regular (6+), Veteran (16+), Legend (31+), Immortal (51+). I added them as a joke. They turned out to be the thing people actually look at — "oh I'm finally a Regular" — which is exactly the wrong incentive for a fair rotation tool and exactly the right one for getting people to keep using it.
  • Filter by team / challenge / game — once one team had three rotations going (standup, oncall, demo-running), the question shifted from "who got picked" to "who got picked for what." The filters let a manager answer that in two clicks. The answer is almost always "the math is fine, your memory is biased."

A subtle anti-pattern I avoided: the first version had a "Streaks" tab. Looked great. The problem was that streak data invites celebration — "Diana is on a 4-day streak!" — which is exactly the framing the tool is supposed to kill. Got rid of it. The app is for picking fairly, not for gamifying speaking up.

What didn't work — the stuff that's not in the screenshots

A few things I tried and pulled back:

  • A longer, more dramatic spin animation with sound effects. Looked great in isolation. In a standup it became the bit, and the bit took the meeting hostage — every spin felt like Wheel of Fortune. Wound it back to a ~3 second total animation that lands cleanly. A picker that takes 8 seconds per pick eats 64 seconds of standup time in an 8-person team. Not free.
  • An "exempt" toggle to skip someone (out sick, traveling). Built it, removed it. The depleting pool is forgiving — if you can't speak today, the round just continues without you and you're up first next round. Adding an exempt UI created the very gap-tracking workload the tool was meant to eliminate.
  • Server-side state. Started writing it. Killed it. localStorage is the right answer for a tool one person runs in their browser to pick a name; a server adds account management, sync conflicts, hosting cost, and a privacy story to maintain — for zero functional benefit at the team-of-one scale.

The app is about 35 React components, no backend. The whole thing fits on a phone screen. The build pipeline runs locally; it deploys as static HTML.

What I'd tell a team adopting this

Three things.

First — the algorithm is non-negotiable, the UI is everything. Whichever picker your team uses (this one, a Slack bot, a paper hat), the depleting pool is the right mechanism for rotation work. The reason "pull a name from a hat without putting it back" exists in every culture is because every culture rediscovered the same math. Use that. But also: pick the tool whose voice matches your team's. Wheel of Death works because my friend's team has dark humor; on a team with different dynamics the same algorithm wrapped in different copy would be the right call.

Second — pick what to put in the rotation deliberately. Standup report-outs, demo-running, retro-facilitating, low-stakes meeting moderation: yes. Oncall: usually yes, but watch for skill gaps (a junior in week 2 doesn't take Sunday-night production pages alone — that's not fairness, that's negligence). Project lead, performance review, hiring loops: no — those want a manager's judgment, not a wheel. Build a different rotation per use case so you don't accidentally rotate the wrong thing.

Third — declare bankruptcy on the past. Don't load six months of standup history into the tool and try to "rebalance." Start the pool fresh on a Monday, tell the team that's what you're doing, and let the math handle it from there. Trying to compensate for past unfairness with current unfairness compounds the problem you started with.

Run it

The repo is at github.com/drlukeangel/fate-games. It's the early version — one team, the Wheel of Death, a slot machine I added because I couldn't help myself, and the depleting pool. Everything lives in browser localStorage. No signup. No telemetry. Reset clears it.

The math is the math. The skull is on purpose.

What's next

The next post in this notebook is on the inverse problem — when a decision genuinely needs a manager's judgment, and a fair rotation would be the wrong answer. Promotions, project lead assignments, deciding who takes a customer-facing escalation. The wheel knows when to spin; the harder skill is knowing when not to.

Keep reading

shares tags: #facilitation · #meetings
projects
Fate Games at Town-Hall Scale: The Grand Prix
May 12
projects
New: Drive Effective, Efficient Agile Meetings
Nov 20
projects
10 Game-Changing Project Management Trends for 2019
Jan 01