> ## Documentation Index
> Fetch the complete documentation index at: https://flux-docs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Server

> The server-side event object returned by Flux.Server.

```luau theme={null}
local MyEvent = Flux.Server("MyEvent")
```

Created only by [`Flux.Server`](/api/flux#flux-server). Server-only, so constructing one on
a client errors.

## Type definition

```luau theme={null}
export type Server<Args... = (...any), Out... = (...any)> = {
	Fire: (self, player: Player, Args...) -> (),
	FireUnreliable: (self, player: Player, Args...) -> (),
	FireAll: (self, Args...) -> (),
	FireAllUnreliable: (self, Args...) -> (),
	Connect: (self, callback: (player: Player, Args...) -> ()) -> { Disconnect: () -> () },
	Once: (self, callback: (player: Player, Args...) -> ()) -> (),
	Wait: (self) -> (Player, Args...),
	OnInvoke: ((player: Player, Args...) -> Out...)?,
}
```

<Note>
  All listener callbacks receive the sending `Player` as their first argument, before the
  event's own arguments.
</Note>

***

## Fire()

```luau theme={null}
function Server:Fire(player: Player, ...: any): ()
```

Sends to one client over the reliable channel.

<ParamField path="player" type="Player" required>
  The recipient.
</ParamField>

<ParamField path="..." type="Args...">
  The payload. Encoded with the event's schema if one is registered, otherwise with the
  dynamic encoder.
</ParamField>

```luau theme={null}
local Notify = Flux.Server("Notify")
Notify:Fire(player, "Welcome back!", 3)
```

<Info>
  Returns immediately. The payload is appended to that player's reliable buffer and flushed
  on the next `Heartbeat`, up to about 16 ms later. See [Batching](/concepts/batching).
</Info>

***

## FireUnreliable()

```luau theme={null}
function Server:FireUnreliable(player: Player, ...: any): ()
```

Sends to one client over the unreliable channel. May be dropped or reordered.

```luau theme={null}
local Position = Flux.Server("Position")
Position:FireUnreliable(player, character.PrimaryPart.CFrame)
```

<Warning>
  Subject to Roblox's `UnreliableRemoteEvent` payload limit. Because Flux batches, the limit
  applies to the whole accumulated frame rather than to your single call, so many unreliable
  sends in one frame can collectively exceed it. Keep unreliable traffic to small,
  self-contained payloads.
</Warning>

***

## FireAll()

```luau theme={null}
function Server:FireAll(...: any): ()
```

Broadcasts to every connected client over the reliable channel, using one `FireAllClients`
rather than a call per player.

```luau theme={null}
local Round = Flux.Server("Round")
Round:FireAll("started", 120)
```

<Note>
  Broadcasts use a separate buffer from per-player sends, and are flushed first. A `FireAll`
  issued after a `Fire(player, ...)` in the same frame will reach that player first, so do
  not interleave the two when order matters.
</Note>

***

## FireAllUnreliable()

```luau theme={null}
function Server:FireAllUnreliable(...: any): ()
```

Broadcasts over the unreliable channel. The right tool for continuous world state.

```luau theme={null}
local Wind = Flux.Server("Wind")

RunService.Heartbeat:Connect(function()
	Wind:FireAllUnreliable(windDirection, windSpeed)
end)
```

***

## Connect()

```luau theme={null}
function Server:Connect(
	callback: (player: Player, ...any) -> ()
): { Disconnect: () -> () }
```

Registers a persistent listener for client sends.

<ParamField path="callback" type="(player: Player, Args...) -> ()" required>
  Invoked once per received message. The sending player is always the first argument.
</ParamField>

<ResponseField name="returns" type="{ Disconnect: () -> () }">
  A plain table with a single `Disconnect` method. Not an `RBXScriptConnection`, so it has
  no `Connected` property and no `Destroy`.
</ResponseField>

```luau theme={null}
local Chat = Flux.Server("Chat")

local connection = Chat:Connect(function(player, message)
	if #message > 200 then
		return
	end
	Chat:FireAll(player.Name .. ": " .. message)
end)

connection:Disconnect()
```

<Warning>
  Listeners are never removed automatically, neither when the creating script is destroyed
  nor on player leave. Only your `Disconnect` call removes one. See
  [Connections](/guides/connections#flux-does-not-clean-up-after-you).
</Warning>

<Info>
  Each callback is dispatched with `task.spawn`, so listeners run concurrently and an error
  in one never blocks the others. Listeners are walked from the end of the list backwards,
  which means the most recently connected runs first. Do not depend on order.
</Info>

<Warning>
  Everything arriving here comes from a client and is untrusted. Generics and schemas
  constrain your own code, not a tampered client's packets. Validate types, clamp ranges and
  verify ownership inside every listener.
</Warning>

***

## Once()

```luau theme={null}
function Server:Once(callback: (player: Player, ...any) -> ()): ()
```

Fires at most once, then removes itself.

```luau theme={null}
local Ready = Flux.Server("Ready")

Ready:Once(function(player)
	print(player.Name, "is the first ready player")
end)
```

<Note>
  Returns nothing. There is no handle, so a `Once` listener cannot be cancelled before it
  fires, and if the event never arrives it stays registered for the session. Use `Connect`
  with a self-disconnect if you need to be able to back out.
</Note>

***

## Wait()

```luau theme={null}
function Server:Wait(): (Player, ...any)
```

Yields the calling thread until the next message on this channel, then returns the sending
player followed by the arguments.

<ResponseField name="returns" type="(Player, Args...)">
  The sender, then the payload.
</ResponseField>

```luau theme={null}
local Vote = Flux.Server("Vote")

local player, choice = Vote:Wait()
print(player.Name, "voted for", choice)
```

<Warning>
  Uses `coroutine.running()` and `coroutine.yield()`, so it has to be called from a yieldable
  thread.

  It also has no timeout. If the message never arrives, the thread parks forever and both it
  and its listener entry stay alive. Guard long waits yourself, using the
  [pattern in Connections](/guides/connections#once-and-wait).
</Warning>

***

## OnInvoke

```luau theme={null}
OnInvoke: ((player: Player, Args...) -> Out...)?
```

Assign a function to handle client invocations. It receives the player first, then the
client's arguments, and may return any number of values.

```luau theme={null}
local Shop = Flux.Server("Shop")

Shop.OnInvoke = function(player, itemId: string)
	local price = priceOf(itemId)
	if not price then
		error("Unknown item: " .. itemId)
	end
	if not charge(player, price) then
		return false, "insufficient_funds"
	end
	return true, itemId
end
```

<Info>
  This is a property with an interposed setter, not a method. Flux catches the assignment
  through `__newindex` and stores the handler in a module-level table keyed by event name.

  Three consequences follow: there is exactly one handler per name, assigning twice replaces
  rather than adds, and every `Server` object built with that name shares it.
</Info>

<ResponseField name="Error handling" type="pcall">
  The handler runs under `pcall`. Errors are caught, transmitted as a message string, and
  re-raised on the client by `Invoke`. Stack traces and error objects do not survive, so
  return a structured result if the caller needs to branch on failure.
</ResponseField>

<ResponseField name="Concurrency" type="task.spawn">
  Each request is handled in its own thread, so a yielding handler never blocks other
  requests. Responses may therefore return out of order.
</ResponseField>

<Note>
  With no handler registered, incoming requests are silently dropped and the client yields
  until its 60-second timeout. Register handlers during startup.
</Note>

<Warning>
  There is no `Server:Invoke`. The server cannot invoke a client. See
  [Invocations](/guides/invocations#direction).
</Warning>

***

## Shared state

The object itself carries almost nothing. Every operation looks up module-level state
through `self._id`.

<ResponseField name="self._id" type="string">
  The channel name. Private.
</ResponseField>

<ResponseField name="self._schema" type="{ Types.Type }?">
  The schema passed at construction. Private.
</ResponseField>

```luau theme={null}
local a = Flux.Server("Ping")
local b = Flux.Server("Ping")

a:Connect(print)
b:Fire(player)  -- runs the listener registered on `a`
```

<Tip>
  This makes it safe to call `Flux.Server("Name")` from several modules instead of threading
  one object through your codebase. It also means an accidental name collision silently
  merges two systems' traffic, so namespace your names in a large place, as in
  `"Combat.Hit"` or `"Shop.Purchase"`.
</Tip>

## Next steps

<CardGroup cols={2}>
  <Card title="Client" icon="desktop" href="/api/client">
    The other half of the pair.
  </Card>

  <Card title="Events guide" icon="tower-broadcast" href="/guides/events">
    Patterns and pitfalls in prose.
  </Card>
</CardGroup>
