Flow control simulator
Combine concurrency, throttling, rate limiting, batching, debounce, singleton, and priority, and watch how Inngest schedules runs over time.
Pick a scenario, turn controls on and off, and press Play. The simulator applies each control in the documented order: rate limiting and batching before scheduling, debounce and singleton when scheduling, then throttling and step concurrency when steps execute.
Ten events at once and a limit of 5 executing steps. Five runs start right away; the rest wait for a free slot. Try: Turn on throttling or rate limiting and compare.
- Event10
- Queued for a slot0
- Executing0
- Completed10
- Slot in use
Click an event row to add an event, and click an added event to remove it. Click a run to see its log. Drag anywhere else to scrub.
How this simulation works
- Time advances in 50 ms ticks. Durations are rounded to the nearest tick.
- Rate limiting uses GCRA with a burst of floor(limit / 10): that many + 1 events pass at once, then one every period / limit.
- Throttling uses GCRA: limit + burst runs can start at once, then one every period / limit. It applies only to a run's first step.
- Queue order uses the run's scheduled time minus its priority factor, so later steps of older runs sort ahead of newer runs.
- Without key queues, the scheduler scans 8 items from the head of the function's queue per pass. Blocked items at the head can delay other keys.
- A function-level concurrency limit (no key) stops the scan when full, because the queue is FIFO.
- Debounce fires exactly at the end of the quiet period; the real service adds about a second of scheduling delay.
- Retries, failures, step overhead, and network latency are not modeled.
Read the simulator
- Event rows show each tenant's events as they arrive. Events at the same instant stack. A red ✕ means rate limiting or singleton skipped the event, and a hollow dot was replaced by a later debounced event. Dashed outlines are events that haven't arrived yet. Click a row to add an event, and click an added event to remove it.
- The flow control band shows what each control is doing at the playhead. Scheduling rows hold debounce and batch timers, singleton locks, and rate-limit skips. The queue row shows runs waiting to start, with the front of the line at the playhead. A dot's color shows why it waits: a concurrency slot, throttle capacity, or blocked work from other keys. Meters under a row's label show slots in use and the throttle or rate-limit capacity left.
- Lanes show runs executing. A solid bar is an executing step, and a dashed bar is a sleep, which holds no concurrency slot. A check marks a completed run, and a red ✕ a cancelled one. Hover a run for its timing, or click it to see its log.
- The line under the diagram counts events and runs in each state at the playhead, and doubles as the legend.
- Runs has per-tenant results and one row per run for the whole simulation. Log explains each decision in order.
Every function in the simulator has a step concurrency limit, 5 by default. The Code tab shows the TypeScript function configuration for the current settings. Tenants map to event.data.tenant_id.
Limits of the model
The simulator is a teaching model, not a benchmark. It runs in 50 ms ticks, doesn't model retries, failures, or network latency, and simplifies how the scheduler scans a function's queue. Open How this simulation works under the simulator for the full list of assumptions.