02Case study / Games
Gacha Lab
An economy design tool that shows what a gacha banner's rules really do, to revenue and to the players who never pay.
Open Gacha Lab (opens in a new tab)Read the code (opens in a new tab)
Introduction
Gacha Lab is an economy design tool that plays a gacha season out across up to a million pretend players.
New to gacha? A quick dictionary
- Gachagah·chuhnoun
- A game mechanic where players spend currency on random draws for characters or items, and the games built around it. The name comes from gachapon, Japan's capsule-toy machines.
- Bannernoun
- A limited-time event built around a featured legendary with boosted odds. Its rules set the odds, the pity, and the 50/50.
- Seasonnoun
- The days a simulation runs, 30 by default. Each day, the players who log in collect their free gems, buy if they pay, and pull.
- Pullnoun, verb
- One try on a banner, paid for with gems. Genshin Impact calls it a wish; Honkai: Star Rail, a warp.
- Legendarynoun
- The rarest prize, usually a 5-star character or item.
- Pitynoun
- The rule that raises the odds the longer a player goes without a legendary. Soft pity is where the odds start climbing; hard pity is where a legendary is certain.
- The 50/50noun
- The chance a legendary is the featured one rather than a different one, often 50%. With a guarantee, losing it makes the next legendary the featured one.
- Whales + dolphinsnouns
- The biggest spenders, a tiny share of players (0.2% in Gacha Lab), and the mid-size spenders who pay far less (1.1%).
The goal: show what a banner's rules really do, to revenue and to the players who never pay. You set the rules, the store, and the player mix, then watch the season play out. It's live, free, and open to anyone.
Most economy tuning happens in a spreadsheet, one number at a time. But a spreadsheet can't show you the trade. Make pity kinder and free players finally get their character, but the whales who were going to spend anyway spend less. I built Gacha Lab to put both halves of that trade on one screen.
- Economy design
- The model is mine, and so is everything built around it: the interface, the motion, and the published tool.
- Public
- Live and free, with no sign-in and no tracking beyond anonymous daily counts.
- Sourced
- Banner rates come from the games' own disclosures and large public pull datasets. The money comes from the only gacha publisher that has ever released per-player spending.
- Published carefully
- The model covers more banners than the site shows. I only publish games I know well enough to vouch for. The rest stay behind a flag until someone who plays them has checked them.
- 9
- Real banners on the live site
- Genshin Impact, Honkai: Star Rail, and Zenless Zone Zero, each with its character and weapon banner, plus Honkai Impact 3rd and both of League of Legends' Sanctum banners. Each has its own rules. The 3 HoYoverse games share HoYoverse's US store prices, as they do in the games.
- 1,000,000
- Players a season
- The biggest sample the tool offers. A season plays out in about 5 seconds.
- 6 of 6
- Published figures matched
- Spend per payer, spend per player, paying share, revenue concentration, and both band averages all land inside the bands set around the published figures. A test fails if any of them drifts out.
The Problem + Solution
How do you let someone change one rule and see, honestly, what it costs in money and in players?
- Problem
- Gacha rules are public. What they do isn't. The rates, the pity, and the 50/50 are all published. Players argue about whether a banner is generous. Designers argue about whether a change will cost revenue. Both sides are guessing, because the only people with the data are the ones who can't publish it.
- Solution
- A simulator, not a calculator. A calculator gives you the odds of one pull. A simulator gives you a season: 10,000 people with different budgets and appetites, logging in on different days, running out of gems at different moments, and the money that falls out of all of it.

Accuracy + Transparency
Clear about how sure it is
A tool like this is only worth using if you can trust it. So I documented exactly how sure it is of each part, and the tool itself says to treat its results as a starting point, not a forecast.
Verified
Every banner rule
Checked against the exact math with a million legendaries per rule set. The pity curves, the 50/50, the guarantee, sparks, and free copies are right to the decimal.
Fitted
The money
Tuned to 6 published per-player figures at once, with a test that fails if any of them drifts out of range.
Not checkable
A season's total revenue
No publisher has released revenue for a single banner, so there's nothing to check it against. The tool lands each per-player figure inside its band, with the right shape across payers, and claims nothing beyond that.

Settings that explain themselves
On HoYoverse's character rules, soft pity nearly always lands the legendary before hard pity is ever reached. Moving hard pity to pull 85, 95, or 100 changes revenue by exactly 0.00%.
So instead of a setting that seems to do nothing, the tool tells you why: “almost never reached (<0.01%).” Bring it down into the climb, and the label shows how many legendaries it now settles.

Outcomes in proportion
The 3 counts were hard to weigh against each other on their own, so I drew them in proportion, in the field's own colors, each with its share.
Key Decisions
Getting the money right
The banner math was verified early and never moved. The money was the hard part, because that's where public data runs out. I pushed the model the way designers and players would and traced each surprising result to its cause. 3 of the fixes that came out of it:
Making prices matter
- <0.1%
- Revenue moved when any of the 5 smaller packs doubled in price
- +32.7%
- Revenue when the $99.99 pack doubled
- 19 of 23
- Presets unchanged by the fix, with calibration held to the cent
What testing showed
Testing across 20,000 players and 8 sets of dice showed that changing a pack's price barely moved revenue, except on the biggest pack.
The options
- Assume the prices weren't reaching the model. Measuring showed they were. (ruled out)
- Look at how buyers choose. They picked packs by how many gems a pack held, never by what it cost. (taken)
The fix
Buyers now spend as little money as they can for the gems they need: the cheapest pack that finishes the job, or else the best price per gem they can afford.
The cause
A whale needs more gems than any single pack holds, so the choice always fell through to “the most gems I can afford,” and price was ignored outright. In a unit test, it would buy a $500 pack for 8,080 gems over a $50 pack for 3,880.
The result
Real stores already make the biggest pack the best value, so calibration held to the cent. Where a store's ladder is out of order, the model now shops the way players do. In a banner I haven't published yet, Umamusume's $69.99 pack costs more than two $33.99 packs, so it skips it.
Measuring what a giveaway really costs
- $80,930
- Free gems priced at store rates
- $180
- Their real cost in revenue, measured at the time
- 450×
- The overstatement the fix removed
What testing showed
The “free gems given away” tile read $80,930 beside $3,391 of revenue, and it never moved when the rules changed. It was pricing every free gem at store rates, counting currency handed to players who would never have bought any.
The options
- Price every free gem at what the store charges, as the tile did. (ruled out)
- Run the same season with nothing given away, same players and same dice, and take the difference. (taken)
The fix
The tile now reports what the giveaway costs in revenue, in dollars, averaged over several sets of dice.
The result
The tile now measures the giveaway instead of pricing it. At the time, the real cost was $180, not $80,930, and on Honkai Impact 3rd, $25, not $91,032.
The tradeoff
Measured on one season, the cost could land anywhere from $5 to $360. Averaging over several sets of dice narrowed that to $64 to $189, at the price of a figure that deliberately doesn't move when you re-roll the luck.
Reconciling 2 sources that seemed to disagree
- 86.6%
- Revenue from the top tenth of payers in a cross-genre study
- 80.1%
- From the top tenth in a publisher's filing
- 83%
- From the top tenth in Gacha Lab, at a million players
The challenge
The money had to match what little spending data has been published, and 2 sources seemed to disagree about the biggest spenders. A publisher's filing put the top 0.2% of players at about $750 a month. A cross-genre study put whales at 86.6% of all revenue.
The options
- Pick one source as the anchor and fit the model to it. (ruled out)
- Put both on the same population first, then fit the model to every published figure at once. (taken)
The fix
The defaults are fitted against all 6 published per-player figures at once, and the money panel shows the one share that can be compared with research: the biggest tenth of payers.
The insight
On the same footing, the 2 sources agree. The study's whales are 0.20% of players in data where only 2.09% pay, which makes them the top tenth of payers, the same group as the filing's top 10.4% of payers. Both put that group at 80 to 87% of revenue.
The result
Every per-player figure now lands inside the band set around its published value, with a test that fails if any of them drifts.

The Craft
Spending paced across the season
Players pace their spending across the season, funding roughly what's left divided by the days left. Free daily gems can stand in for a purchase. And because each day's share sizes the purchase, the whole price ladder sells.
Pack money spent on day 1
Before100%AfterPaced across the season
Money through a single pack
Before91%AfterSpread across the ladder

Every pack shows its share
Each pack shows its share of the season's money, so the answer to “why didn't this price change move revenue?” is right there on screen, not left to be guessed at.

Each dot is 84 players
One dot per player stops working fast. At 100,000 players, dots small enough to fit turn the field into gray mush, and at a million they'd be smaller than a pixel. So past about 12,000 players, the field draws one player in N, with the same stride for every type so the proportions hold. At a million, that's 1 in 84.
The label had to change with it. A label that silently stops being true is worse than a less ambitious one that is.

Every dot opens a player
Any dot opens the player behind it. The model is only trustworthy if you can pull one person out of it and check that their season made sense.
Learnings
Every surprising result had a real cause, and the model is more accurate for having chased them down. What I'd carry into any economy work:
- 01
Put 2 sources on the same population before you let them disagree.
- 02
Measure before changing anything. Twice, measuring first showed the real cause was somewhere else.
- 03
Break the code to test the test. That's how I found that no test would have caught a change that silently zeroed a visitor's setting. Now one does.
- 04
Re-measure the calibration every time the model changes. A stale figure in the docs is a quiet lie.