Skip to main content

What is the Lottery class?

Illuminate\Support\Lottery is a utility class that lets you express probability-based operations as a clean, fluent API. Instead of sprinkling random_int() calls across your codebase, you can write self-documenting code like “run this 1 in 100 times”.
The implementation lives in src/Illuminate/Support/Lottery.php. Laravel itself uses this class internally for session garbage collection, cache lock pruning, and more.

Basic usage

Integer ratio odds

Pass $chances and $outOf to express “win chancesoutofchances out of outOf times”.

Float odds

Omit $outOf and pass a float between 0.0 and 1.0 to use it directly as a probability.
A float value greater than 1.0 throws a RuntimeException.

Boolean return without callbacks

When you do not set winner or loser callbacks, choose() returns true on a win and false on a loss.

Run multiple times

Pass an integer to choose($times) to run the lottery that many times and receive an array of results.

Passing Lottery as a callable

Lottery implements __invoke, so you can pass an instance directly anywhere a callable is expected.

Practical use cases

1. Cache pruning (run once every 100 requests)

Use Lottery to spread maintenance work across requests instead of running it on every request.

2. Telemetry sampling (detailed log for a subset of requests)

Recording full telemetry on every request is expensive. Sample a fraction instead.

3. A/B-style behavior

Split users across two code paths with a controlled probability.

4. Randomizing scheduled tasks

Avoid all servers in a cluster running the same expensive task simultaneously.

Probabilistic patterns in Laravel core

Laravel uses probabilistic maintenance patterns throughout the framework. Some implementations were written before the Lottery class existed and use random_int() directly, but they follow the same philosophy.
1

Session: garbage collection

Illuminate\Session\Middleware\StartSession::configHitsLottery() reads config/session.php and uses random_int to decide whether to run GC on the current request.
2

DatabaseLock: pruning expired locks

Illuminate\Cache\DatabaseLock::acquire() applies the same integer ratio pattern to prune stale lock rows on every lock acquisition.
3

DB::whenQueryingForLongerThan — passing a Lottery instance

Because Lottery implements __invoke, you can pass it directly as the callable argument to APIs like DB::whenQueryingForLongerThan.
While Session and DatabaseLock use random_int() directly, using the Lottery class gives you testability through alwaysWin(), alwaysLose(), and fix(). Prefer Lottery in your packages for this reason.

Testing with Lottery

Because Lottery uses random_int() internally, you need deterministic control in tests. Laravel provides three APIs for this.

Lottery::alwaysWin() — force every draw to win

Lottery::alwaysLose() — force every draw to lose

Lottery::fix() — pin results to a sequence

Control each draw individually by providing an array of true/false values.
alwaysWin(), alwaysLose(), and fix() all mutate a global static property. Always call Lottery::determineResultNormally() in tearDown() to prevent test pollution.

Lottery::setResultFactory() — inject a custom factory

For fine-grained control, inject a custom callable that receives $chances and $outOf.

Package development patterns

Register maintenance in a service provider

Spread expensive housekeeping work across incoming requests instead of running it on a schedule.

Make odds configurable

Let package users tune the probability without touching your code.

Sampling middleware

API reference

The Macroable trait

Learn the API extension pattern for adding methods to existing classes.

The Conditionable trait

Learn conditional fluent chains with when() and unless().
Last modified on July 13, 2026