Skip to content
Back to skills

Roblox Networking

ASecurity

Client-server communication - RemoteEvent, UnreliableRemoteEvent, RemoteFunction, what survives serialization, typed remote modules, server validation and rate limiting, bandwidth (deltas, buffers, batching), synced time, Zap/Blink. Use when adding remotes, syncing state to clients, debugging nil/lost remote arguments, or reducing lag and bandwidth.

  • 5 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 29, 2026
ai-agentsrustdebuggingsecurityperformance

Works with

  • cli

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 29, 2026

npx -y skills add EL4CTEO/roblox-skills --skill roblox-networking --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Roblox Networking?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Roblox Networking
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/el4cteo-roblox-networking/badge)](https://www.skillsdirectory.com/skills/el4cteo-roblox-networking)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: roblox-networking
description: Client-server communication - RemoteEvent, UnreliableRemoteEvent, RemoteFunction, what survives serialization, typed remote modules, server validation and rate limiting, bandwidth (deltas, buffers, batching), synced time, Zap/Blink. Use when adding remotes, syncing state to clients, debugging nil/lost remote arguments, or reducing lag and bandwidth.
---

# Roblox networking

## Pick the right channel

| Channel | Delivery | Use for |
| --- | --- | --- |
| `RemoteEvent` | Reliable, ordered | Requests (client→server), game events, UI updates. The default. |
| `UnreliableRemoteEvent` | May drop or reorder; payload ≤ **1000 bytes** (larger payloads are dropped) | Continuous, superseded-by-next data: aim direction, cosmetic VFX, positions of non-physics objects. |
| `RemoteFunction` | Request/response, yields caller | Client→server queries that need an answer (e.g. "can I buy X?"). |
| Attributes / properties | Automatic replication server→client | Persistent state clients read (health, team, round state). |
| Physics replication | Automatic for owned assemblies | Moving parts; see `roblox-physics`. |

Never use `RemoteFunction:InvokeClient`: if the client errors, disconnects, or never returns, the server
throws or **yields forever**. Use a `RemoteEvent` to the client and another back if you need a reply.

## Defining remotes once (typed)

Create remotes on the server; clients wait for them. Centralize names so typos can't happen.

```luau
--!strict
-- ReplicatedStorage/Shared/Net.luau
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")

local FOLDER_NAME = "Remotes"
local IS_SERVER = RunService:IsServer()

local folder: Instance
if IS_SERVER then
	folder = ReplicatedStorage:FindFirstChild(FOLDER_NAME) or Instance.new("Folder")
	folder.Name = FOLDER_NAME
	folder.Parent = ReplicatedStorage
else
	folder = ReplicatedStorage:WaitForChild(FOLDER_NAME)
end

local function get<T>(className: string, name: string): T
	if IS_SERVER then
		local existing = folder:FindFirstChild(name)
		if existing then
			return existing :: any
		end
		local remote = Instance.new(className)
		remote.Name = name
		remote.Parent = folder
		return remote :: any
	end
	return folder:WaitForChild(name) :: any
end

return {
	RequestPurchase = get("RemoteEvent", "RequestPurchase") :: RemoteEvent,
	InventoryChanged = get("RemoteEvent", "InventoryChanged") :: RemoteEvent,
	AimDirection = get("UnreliableRemoteEvent", "AimDirection") :: UnreliableRemoteEvent,
	GetShopStock = get("RemoteFunction", "GetShopStock") :: RemoteFunction,
}
```

## Server handler template

Every `OnServerEvent`/`OnServerInvoke` handler: **rate limit → type-check every argument → check
game rules → act**. The first parameter is always the real `Player` (Roblox fills it in; it can't be forged).

```luau
--!strict
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Net = require(ReplicatedStorage.Shared.Net)

local ITEM_PRICES: { [string]: number } = { Sword = 100, Shield = 150 }
local MIN_INTERVAL = 0.25
local lastRequest: { [Player]: number } = {}

Net.RequestPurchase.OnServerEvent:Connect(function(player: Player, itemId: unknown)
	local now = os.clock()
	if now - (lastRequest[player] or 0) < MIN_INTERVAL then
		return -- rate limited
	end
	lastRequest[player] = now

	if typeof(itemId) ~= "string" or #itemId > 64 then
		return -- malformed: never trust argument types
	end
	local price = ITEM_PRICES[itemId]
	if not price then
		return -- unknown item
	end
	-- check the player's server-side balance, deduct, grant, then notify:
	Net.InventoryChanged:FireClient(player, { added = itemId })
end)

game:GetService("Players").PlayerRemoving:Connect(function(player)
	lastRequest[player] = nil -- avoid leaking Player keys
end)
```

Full validation toolkit (NaN/inf checks, instance ownership, distance and cooldown checks): `roblox-security`.

## What survives the wire

- Tables are **copied**: identity and metatables are lost; functions become `nil`.
- Don't mix array and dictionary keys in one table; don't put `nil` holes in arrays.
- Non-string dictionary keys (Instances, numbers in sparse tables) are converted to strings — send arrays of pairs instead.
- Instances arrive as `nil` if the receiver can't see them (e.g. `ServerStorage` items, or parts not
  yet streamed in on the client).
- Supported: `nil`, booleans, numbers, strings, tables, `buffer`, Roblox datatypes (`Vector3`, `CFrame`,
  `Color3`, `EnumItem`, ...), and replicated `Instance` references.
- Server→client ordering vs. property replication is not guaranteed: a remote may arrive before or
  after a property change it relates to.

## Bandwidth and CPU

- Send **changes**, not full state (item added, not the whole inventory). Send on change, not per frame.
- Throttle input-driven sends on the client (e.g. aim at most 20 Hz) and still rate-limit on the server.
- Send IDs/enums as small numbers; quantize floats; pack hot, high-frequency data into a `buffer`.
- Batch many small messages into one per frame (queue in a table, flush on `Heartbeat`).
- Server-side `TweenService` replicates every frame and looks jittery: tween on clients instead.
- VFX: the server decides the outcome and fires a minimal event; each client spawns effects locally.
- Profile with the MicroProfiler (`ProcessPackets`, `Allocate Bandwidth and Run Senders`) and the
  Developer Console **Network** tab.

```luau
--!strict
-- Pack a hit notification into 11 bytes instead of a table with string keys.
local function encodeHit(targetId: number, damage: number, position: Vector3): buffer
	local b = buffer.create(11)
	buffer.writeu32(b, 0, targetId)
	buffer.writeu16(b, 4, math.clamp(math.round(damage), 0, 65535))
	buffer.writei16(b, 6, math.clamp(math.round(position.X), -32768, 32767))
	buffer.writei16(b, 8, math.clamp(math.round(position.Z), -32768, 32767))
	buffer.writeu8(b, 10, math.clamp(math.round(position.Y / 4), 0, 255))
	return b
end

local function decodeHit(b: buffer): (number, number, Vector3)
	return buffer.readu32(b, 0),
		buffer.readu16(b, 4),
		Vector3.new(buffer.readi16(b, 6), buffer.readu8(b, 10) * 4, buffer.readi16(b, 8))
end

print(decodeHit(encodeHit(42, 25, Vector3.new(10, 20, 30))))
```

For many remotes with hot paths, schema-driven generators (**Zap**, **Blink**) produce typed,
validated, buffer-packed remotes automatically. Adopt them when profiling shows network cost.

## Time and latency

- `workspace:GetServerTimeNow()` is a synchronized clock on server and clients: send a start timestamp
  and let clients compute progress locally (round timers, cooldown bars, projectiles).
- `player:GetNetworkPing()` returns round-trip network latency in seconds (clients may only query
  `LocalPlayer`); use it to size lag-compensation windows.
- Don't send countdown ticks every second; send the end time once.

More patterns (request/response with timeouts, state snapshots + deltas, per-frame batching, client
prediction): [references/patterns.md](references/patterns.md).

## Related skills

`roblox-security` (validation, anti-exploit), `roblox-architecture` (where remotes live),
`roblox-physics` (network ownership, server authority), `roblox-performance`.

Files in this skill

  • SKILL.md7.1 KB
  • references/patterns.md5.3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.