How It Works
How Rivo Queue works
This page explains what happens to a player from the moment they press connect
until they are in the game, and how every setting changes that. Read it once
and the rest of the config will make sense.
1. The connection, step by step
When a player connects, Rivo Queue holds the connection (a FiveM "deferral")
and shows a card on their loading screen. Behind the card, this runs in order:
Identifiers are read. The player is tracked by
Config.primaryIdentifier
(licenseby default), falling back throughConfig.identifierFallback.
No usable identifier means the connection is refused.Reconnect check. If the same player already has a place in line, or had
one in the last few seconds, it is carried over (see Reconnect grace).Gates run. Each gate can refuse the connection. Cheap checks go first so a
banned player never costs a Discord request.Order Gate What it checks 10 banThe ban list ( queue ban add, panel,addBan)15 blockTemporary blocks left by queue kick20 identifiersConfig.requireIdentifiers30 throttleToo many connection attempts in a short window 40 whitelistConfig.whitelist, when enabled45 guildConfig.discord.requireInGuild50 altsConfig.altDetection, when enabledPlayer history is recorded for the panel's Users tab
(Config.playerHistory). Refused players are recorded too.Processing delay.
Config.cooldownseconds.Priority is resolved from every source (see Priority).
Maintenance check. If maintenance mode is on, only the allowed tiers get
past this point.Startup hold. Right after the server boots, everyone waits out
Config.joinDelayunless their tier hasskipJoinDelay.Queue full check.
Config.maxQueueSize, if set.Admit or queue. The player walks straight in when their tier bypasses the
queue, or when nobody is waiting and there is a free slot. Everyone else joins
the queue and sees their position, wait time, estimate and priority.Admitted. Players who never had to wait see the branded "You are in" card
forConfig.ui.brandHoldSeconds. Then the deferral is released and the game
starts loading.Loading. The player now holds a slot while they download and load. When
they spawn in (playerJoining), the slot becomes a normal player slot.
A player who closes FiveM while waiting is removed after Config.queueTimeout
seconds of silence. A player who is admitted but never finishes loading gives
their slot back after Config.connectingTimeout seconds.
2. Slots
The queue decides who gets in by counting free slots every second:
free = sv_maxClients
- players online
- players loading (admitted, not spawned yet)
- players being admitted this second
- slots held for crashed players (reconnect grace)
- Config.reservedSlots (skipped for tiers with reservedSlot = true)
Counting players who are still loading is what stops the classic queue bug of
admitting 40 people into 30 slots and kicking 10 of them at the loading screen.
queue slots in the console prints exactly these numbers. It is the first thing
to check when the server looks empty but nobody is getting in.
hardcap kicks players as soon as the server is full, which breaks any queue. It
is stopped automatically on start (Config.autoStopHardcap).
3. Priority
Priority is a number of points. More points means further forward.
Sources
Points come from sources. A player can match several at once.
| Source | Where it comes from |
|---|---|
config |
Config.priorityList, hardcoded identifiers |
store |
Rows saved with queue prio add, the panel, or addPrio (JSON file or MySQL) |
discord |
Config.discord.roles, looked up through your bot |
ace |
Config.acePriority and txAdmin admins (Config.txAdmin) |
| your own | Any resource can add a source with registerPrioritySource (see Developer API) |
Rows match on any identifier the player has, so a row saved againstdiscord:123 still applies to a player tracked by license.
Config.priorityMode decides how matching rows combine: 'sum' adds them,'max' takes the highest. Stored rows can expire.
Tiers
A row can also name a tier from Config.tiers. The player gets the best tier
named by any of their rows, where "best" means highest in the Config.tiers
list. A tier gives:
| Field | Effect |
|---|---|
points |
A minimum. A VIP with a 2,500 point tier is worth at least 2,500 |
bypassQueue |
Skips the queue whenever a slot they can use is free |
reservedSlot |
Can use the slots held back by Config.reservedSlots |
skipJoinDelay |
Ignores the post-restart hold |
badge |
Name shown on the card and in the panel |
4. Order in the queue
Every second the queue is sorted by score, highest first:
score = priority points + time waited bonus
- Time waited bonus (
Config.drift). Every waiting player gainspointsPerMinutepoints per minute. WithmaxPoints = 'auto'the bonus stops
one point below your cheapest tier, so a long wait can beat everyone without
priority but never beats a paying tier. - Ties go to whoever joined the queue first.
- Head lock (
Config.headLock). Once a player is first in line, nobody who
joins later can push them back to second. - Admin pins. Moving a player in the panel pins them to that position until
they get in, leave, or you release the pin. Pins override everything above.
The estimated wait on the card is the average time between recent admissions
multiplied by the player's position.
5. Restarts: startup hold and staged release
After a server boot, every resource needs time to start, and the whole community
tries to connect at once.
- Startup hold. For
Config.joinDelayseconds everyone is held on a
"server is starting" card. Restarting only this resource does not trigger it. - Staged release. For
Config.stagedRelease.durationSecondsafter the hold
ends, the queue admits at mostplayerspeople everyeverySecondsseconds.
During this window players are not let straight in, they go through the queue
so priority order is respected. Tiers withbypassQueuestill skip it.
6. Reconnect grace
If a player's game crashes while they wait, they do not go to the back.
- Waiting players who come back within
Config.grace.positionSecondsget
their original queue time back, which puts them back in their old position. - Admitted players who crash while loading get their slot held for
Config.grace.slotSeconds. The held slot counts as taken, and they walk
straight back in when they reconnect.
Kicked or refused players never get grace.
7. Discord
With a bot token and guild ID set, Discord roles can grant priority, whitelist
access and guild membership checks. Lookups are cached forConfig.discord.cacheSeconds.
When Discord is slow or down:
- Priority fails open. The player still connects, just without role points
for that connection. Cached roles keep working through short outages. - Whitelist and guild checks fail closed. Letting everyone in would switch
your whitelist off. Players who pass the whitelist another way (ACE, the
identifier list) are not affected. - Rate limits pause lookups and serve cached roles until Discord allows
requests again. - A rejected token turns Discord features off and logs an error until restart.
8. Storage
Priority rows, bans and player history live in one of two backends:
- JSON (default when oxmysql is not running): files in
data/. Writes are
batched, and a corrupt file is never overwritten. - MySQL (default when oxmysql is running): tables from
queue.sql, created
automatically on first start.
Expired rows are cleaned every Config.pruneIntervalMinutes. Maintenance state
is always kept in data/state.json so it survives a restart.
9. Maintenance mode
queue pause [duration] [reason] or the panel restricts connections to chosen
tiers (Config.maintenance.defaultAllowTiers by default). Players already on the
server are not touched. It persists through restarts and lifts itself when a
duration was given.
10. Logging, metrics and events
- Console.
Config.consoleInfoprints joins, admits and refusals.Config.debugprints more. - Discord webhook. Four categories you can switch on separately:
denial,admin,milestoneandtraffic. Messages are batched and retried on rate
limits. Player names never ping anyone. - Metrics. Counters, peak queue, wait average and p95 per tier, and refusals
by gate since the last restart. Seequeue metrics, the panel, orgetMetrics. - Server events for your own resources:
rivo_queue:queued,rivo_queue:admitted,rivo_queue:joined,rivo_queue:left,rivo_queue:denied,rivo_queue:flagged,rivo_queue:adminandrivo_queue:milestone. Payloads are listed in Developer API.