> For the complete documentation index, see [llms.txt](https://docs.marioded.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.marioded.com/use-reverse/network.md).

# Lobby and proxy setup

Connect gameplay servers, a selection lobby, and replay servers through your proxy.

Give players one place to choose a recording, then send them to a dedicated replay server. This guide connects **recorder → shared storage → lobby → player**.

## Before you begin

* A working local recording/playback test.
* A proxy with stable backend names, such as `replay-lobby` and `replay-1`.
* Shared SQL replay storage reachable by every role.

{% hint style="info" %}
**Two systems, two jobs:** SQL stores your replay archive. Availability tells the lobby which replay servers are online; it can use that SQL database or Redis.
{% endhint %}

## Architecture

```mermaid
flowchart LR
  Recorder[Gameplay server: Recorder] --> Storage[(Shared replay storage)]
  Lobby[Selection server: Lobby] -->|Read catalog| Storage
  Player[Replay server: Player] -->|Load events and terrain| Storage
  Lobby <-->|Selection and liveness| Availability[(SQL or Redis availability)]
  Player <-->|Heartbeat and handoff| Availability
  Lobby -->|Proxy transfer| Player
```

Two separate systems must be shared:

1. **Replay storage:** typically one SQL database used by recorder, lobby, and player.
2. **Availability:** either the database backend or a shared Redis endpoint used by lobby and player.

Redis contains liveness and short-lived handoffs, not `.rpl` event data or chunk snapshots.

## 1. Configure the proxy

Register your lobby and replay servers under stable proxy names, for example `replay-lobby`, `replay-1`, and `replay-2`. Players must be able to connect to those names through the proxy.

Transfers use the `BungeeCord` plugin-message channel with the `Connect` subchannel. For BungeeCord-compatible proxies, make sure that channel is supported. On Velocity, enable its BungeeCord plugin-message compatibility option where required by your proxy configuration. No separate Reverse proxy plugin is supplied.

Do an ordinary manual proxy transfer first. Fix forwarding/server-registration issues before debugging Reverse's selection flow.

## 2. Share storage

Use the same SQL connection settings on all participating roles. Merge this section into each `config.yml`, retaining the other generated storage fields:

```yaml
storage:
  type: DATABASE
  database:
    type: mariadb
    host: database.internal
    port: 3306
    database: replay
    username: reverse
    password: 'replace-with-your-password'
  fallback-to-spatial: false
```

The example hostname is a placeholder. Create the database and a suitable account yourself. Reverse's backend initializes its schema; it does not provision a database server.

Do not enable local fallback on a worker and expect its private disk to be visible elsewhere. See [storage](/configure-and-customize/storage.md).

## 3. Choose availability

Choose **one** backend and use the same choice on the lobby and every replay server.

{% tabs %}
{% tab title="SQL availability" %}

### Use your shared database

On the lobby:

```yaml
network:
  enabled: true
  backend: database
  node-id: replay-lobby
  ping-millis: 5000
  ping-timeout-millis: 15000
```

On the first player server, use the same settings but `node-id: replay-1`. On the second use `node-id: replay-2`. Keep the generated `redis` section even when unused.

Database availability requires SQL storage to have actually opened successfully. `SPATIAL` does not provide a shared SQL availability backend.
{% endtab %}

{% tab title="Redis availability" %}

### Use Redis for coordination

Keep shared SQL replay storage, but change the network backend on both lobby and player:

```yaml
network:
  enabled: true
  backend: redis
  node-id: replay-1
  ping-millis: 5000
  ping-timeout-millis: 15000
  redis:
    uri: redis://redis.internal:6379/0
    command-timeout-millis: 5000
```

Use the lobby's own proxy name on the lobby. All nodes must address the same Redis service/database. Protect the endpoint and credentials as you would any shared backend.
{% endtab %}
{% endtabs %}

## 4. Restart and test

1. Restart backend servers after changing storage/network settings.
2. Make a test recording and wait for save completion.
3. Join the lobby as an owner or administrator.
4. Open `/reverseview` and select the replay.
5. Confirm arrival starts playback on the selected replay server.
6. Stop playback and confirm return to the origin lobby.
7. Repeat with a nonowner and check access denial.

{% hint style="success" %}
**Ready to use:** a viewer can select a saved recording in the lobby, arrive on a replay server, watch it, and return to the original lobby after stopping.
{% endhint %}

## How selection works

Player nodes publish heartbeats. The lobby queries fresh nodes in heartbeat order and chooses the first. It writes a pending selection for the target node/viewer and sends a proxy transfer. The player consumes that selection on join and loads the replay.

Pending selections expire after five minutes and are consumed once. A successful dispatch result means the selection was written and a transfer message sent; it is not confirmation that the proxy completed the connection or the client finished loading.

Availability is not a queue, capacity reservation, or least-loaded matchmaking system. Several viewers can be sent to the same replayer. Duplicate requests by one viewer are guarded while pending.

## Common mistakes

* A node ID is a hostname, UUID, or display title instead of the proxy's server name.
* Lobby and player use different Redis databases or SQL databases.
* One node fell back to local storage at startup.
* A replay template is present on the recorder but not on the player.
* A player worker was switched to network mode without restarting.
* A heartbeat is present, but the proxy cannot reach that server.

{% content-ref url="/pages/1ClQXDROKUIqEESqA9ox" %}
[Troubleshooting](/keep-things-running/troubleshooting.md)
{% endcontent-ref %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.marioded.com/use-reverse/network.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
