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.

1 · Before scheduling
2 · When scheduling
3 · When executing
12s / 12s
  • 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.

1 · Before scheduling
Rate limiting

Skip runs above a start limit per period.

Batching

Collect events into one run.

2 · When scheduling
Debounce

Wait for a quiet period, then run once with the last event.

Singleton

Keep one active run per key.

3 · When executing
on
Step concurrency

Caps steps executing at once. Sleeping runs hold no slot.

Throttling

Queue run starts above a rate. Nothing is dropped.

Priority

Move a tenant's runs forward or back in the queue.

Key queuesEnterprise

Schedule each key separately so one tenant's blocked backlog doesn't delay others.

Start timeout

Cancel runs that wait too long to start.

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.