Skip to content

Waiting Room

Try the interactive example ↓

Virtual waiting rooms for scarce capacity: rooms with FIFO, priority, or random admission, manual and automatic admission, TTL-based sessions with refresh, group fast-tracking, anti-gaming protections, and per-room analytics.

When to reach for it: product-drop launches, ticket on-sales, beta access gating, game login queues, flash sales, ordered admission to any capacity-limited resource.

When not to: background work that machines process belongs to Job Queue; pairing players by skill belongs to Matchmaking.

Concepts

  • Rooms carry a capacity and a status (active, paused, disabled). Creating, updating and deleting rooms, admission, member listing, analytics, and bans require a platform admin token; reading a room, listing rooms, joining and polling do not.
  • Member lifecycle - a member joins as waiting, then is admitted (shown as active from that point), and eventually leaves, expires, or is rejected. Once admitted, position responses drop the position field.
  • Queue strategies - fifo (default), priority (higher priority value is admitted first), or random.
  • Admission is manual (admit by count or by member IDs) or automatic: with auto-admit on, a background sweep promotes waiters whenever capacity is open.
  • Sessions - if the room sets a session TTL, admitted members must refresh periodically; a cleanup worker evicts expired sessions so abandoned members do not hold capacity.
  • Groups - members who join with the same group_id can be checked and admitted together as one atomic unit.
  • Anti-gaming and bans - rejoin cooldowns, join rate limits, and a ban registry have their own page: Bans and anti-gaming.

Create and manage rooms (admin)

snug waiting-room create -r launch-day -c 100 -s priority --session-ttl 600
snug waiting-room list
snug --output json waiting-room get -r launch-day
snug waiting-room update -r launch-day -c 200 -s paused
snug waiting-room delete -r launch-day

get returns the room configuration plus live statistics (active_count, waiting_count, total_admitted, average_wait_seconds, current_admission_rate). Verified behaviors:

  • Creating an ID that already exists fails with 409 CONFLICT - Room already exists.
  • delete refuses a room that still has members: 409 CONFLICT - Room is not empty. Empty it first.
  • --auto-admit is a bare flag on create but takes a value on update (--auto-admit true|false).
  • list (CLI and GET /api/v1/waiting-rooms) takes the shared list parameters: filter on status, queue_strategy, created_by and capacity, and sort by created_at (the default, newest first) or updated_at.

Join and wait

snug waiting-room join -r launch-day -p 75      # -p matters only in priority rooms
snug --output json waiting-room position -r launch-day
snug waiting-room refresh -r launch-day         # extend the session TTL
snug waiting-room leave -r launch-day

Over HTTP, joining is a POST with an optional priority, group, and metadata; captured live:

curl -X POST -H "Authorization: Bearer $SNUG_API_TOKEN" \
  -H "Content-Type: application/json" -d '{"priority": 0}' \
  http://localhost:4000/api/v1/waiting-rooms/launch-day/join
{
  "status": 201,
  "msg": "Created",
  "data": {
    "room_id": "launch-day",
    "member_id": "docs4-other",
    "position": 2,
    "estimated_wait_seconds": 0,
    "status": "waiting",
    "joined_at": "2026-08-28T14:15:27.135772Z",
    "priority_group": "standard"
  }
}

position polls the caller's own place in line and adds ahead_count and priority_effective. In a priority room the order is by priority, not arrival - verified: a member joining with -p 100 landed at position 1 ahead of an earlier member with -p 10, while the same experiment in a fifo room left arrival order untouched. estimated_wait_seconds is derived from the room's admission rate (batch_size per interval_seconds).

Joining a room twice fails with 409 CONFLICT - Already in queue, and polling or leaving when not queued is 404 NOT_FOUND - Not in queue. refresh returns the new expiry as a Unix timestamp: {"success": true, "new_expiry": 1787927148}.

Admitting members (admin)

snug waiting-room members -r launch-day --filter 'status[eq]=waiting'
snug waiting-room admit -r launch-day -c 10            # next 10 by strategy order
snug waiting-room admit -r launch-day -m user-1,user-2 # specific members
snug waiting-room reject -r launch-day -m user-3 -R "abuse" -b 3600

members lists the waiting queue in position order, then the active members in id order; --filter 'status[eq]=waiting' or status[eq]=active narrows it to one of the two, and it pages on the standard list contract.

The admit response reports both outcomes; captured live admitting a member ID that was not queued:

{
  "admitted": [],
  "capacity_reached": false,
  "failed": [ { "member_id": "docs4-ghost", "reason": "Not in waiting queue" } ]
}
  • members lists every status when -s is omitted; pass -s (waiting, admitted, active, expired, rejected) to filter.
  • Admitted members are listed under -s active with an admitted_at timestamp; there is no separate "admitted but not active" listing.
  • reject -b <seconds> combines removal with a temporary ban - see Bans and anti-gaming.

Auto-admission

With auto-admit on, a background sweep promotes waiters whenever the room has free capacity - verified: a member joined as waiting and was active roughly ten seconds later with no manual admit. The sweep runs on a server-wide cadence (WAITING_ROOM_AUTO_ADMIT_INTERVAL_SECONDS, default 10) admitting up to the room's batch_size per pass; the room's interval_seconds only feeds the wait-time estimate, not the cadence.

Groups

snug waiting-room join -r launch-day -g vip-42
snug --output json waiting-room group-status -r launch-day -g vip-42
snug waiting-room admit-group -r launch-day -g vip-42

group-status lists the group's members with positions and a can_be_admitted verdict (does free capacity fit the whole group); admit-group then admits every member atomically - verified with a two-member group into a capacity-2 room (capacity_reached: true).

Analytics (admin)

snug --output json waiting-room analytics -r launch-day

Returns a summary (total admissions, rejections, abandonments, their rates, and min/avg/max wait seconds) plus hourly buckets over the queried window, retained for 7 days by default.

Limits and configuration

Room count cap (10,000 by default), auto-admit cadence and per-pass batch cap, and the session, ban, and analytics cleanup intervals are tunable via the WAITING_ROOM_* variables.

Reference

Interactive example

Queue people for a resource with limited capacity. Admit them in order and free space as active participants leave or time out.

An illustrative example that runs in your browser. No account or API calls required.