Load testing
Prove queue behavior from hundreds to 100k users without paying Cloudflare for every experiment.
For product overview, see the README. For Durable Object semantics, see architecture.md.
In-memory scale test (recommended)
Section titled “In-memory scale test (recommended)”Runs a pure TypeScript queue that mirrors Durable Object semantics (capacity, FIFO, rate-limited admit). Fast enough for 100k users on a laptop.
# defaults to 1000 usersnpm run test:load
LOAD_TEST_USERS=100 npm run test:loadLOAD_TEST_USERS=500 npm run test:loadLOAD_TEST_USERS=1000 npm run test:loadLOAD_TEST_USERS=5000 npm run test:loadLOAD_TEST_USERS=100000 npm run test:loadOptional knobs:
| Env var | Default | Meaning |
|---|---|---|
LOAD_TEST_USERS |
1000 |
Visitors to enqueue |
LOAD_TEST_CAPACITY |
20 |
Concurrent admitted slots |
LOAD_TEST_ADMIT_PER_SECOND |
100 |
Admission rate used while draining |
The test asserts:
- First
capacityjoins are admitted immediately - Remaining visitors wait in FIFO order
- Positions are 1-based and stable
- Drain via leave+tick never skips ahead in line
Durable Object load smoke test (opt-in)
Section titled “Durable Object load smoke test (opt-in)”Exercises real QueueRoom RPC/SQLite. Each join is a DO request, so keep N modest unless you intentionally want a long run.
RUN_DO_LOAD=1 LOAD_TEST_USERS=200 npm run test:load:doRUN_DO_LOAD=1 LOAD_TEST_USERS=500 LOAD_TEST_CAPACITY=20 npm run test:load:doNotes:
- Full
npm testexcludestest/load/** - CI runs a small in-memory smoke (
LOAD_TEST_USERS=50) on every PR via theload-smokejob - 100k DO joins will be slow and burn CPU; prefer in-memory for that scale
- Production cost still hinges on timeslot status check-ins (≈750 RPS budget) and idle alarm cleanup
Interpreting results
Section titled “Interpreting results”The in-memory suite prints a JSON summary:
{ "users": 5000, "capacity": 20, "admitPerSecond": 100, "ticks": 50, "elapsedMs": 42, "joinsPerSecond": 119047}Use that to compare machines and algorithms, not as a Cloudflare billing estimate. Billing is dominated by Worker/DO requests from real browsers, which is why the waiting room polls slowly and never writes KV on the hot path.
