A Roblox game framework built like an operating system. A kernel schedules work under a frame budget, drivers own networking, player data, commerce and anti-exploit, and genre kits cover the systems most games rebuild. The server decides; clients send intents.
Best Roblox framework ever made. No spec covers that claim.
- gateShared suite435 / 435 tests, 51 modulespass
- gateServer suite809 / 809 tests, 56 modulespass
- bootServerKernelv0.9.1, Bootstrap loads Gameok
- gateAuditchannel validators, no High findingspass
- gateFuzzhostile payloads, 0 validator errorspass
- runDiagnosticsF8 panel fed while in Studioon
The life of an intent
One keypress, followed through the whole framework: across the network, through every gate the server puts in front of game code, into a player's saved data and back out to every screen. Scroll to follow it, or pressE.
- 01 / 08
A player presses E
InputDriver publishes
InputDriverInput.Buy, then runs the handler on its own thread. The controller fires the intent with an item id and nothing else. The client asks; it never tells.self.Net.Buy.fire(42) -- declared once in Game.Channels
~198 ns Bus:publish of Input.Buy, the callback's only synchronous work
- 02 / 08
Three bytes, one call
Packet writes a channel id and 42 as a little-endian
Packet and wire typesNumberU16. Every frame queued this heartbeat rides oneFireServer, at most 60 a second.0Bchannel2A4200U16No length prefix client to server. The server assigns channel ids;
0Bis this example's.0 to 16.7 ms waiting for the next heartbeat flush: the largest cost on the client
- 03 / 08
Metered, then decoded
Before reading a frame the server meters the player: 8,000 bytes per heartbeat, 240 frames a second. Only then does the frame decode against its schema.
The inbound pipelineBytes this beat800 / 8,000Frame tokens127 / 128Every call counts as at least 800 bytes, so garbage buffers cannot buy server CPU.
~367 ns a comparable schema decode (Serde, three fixed fields)
- 04 / 08
Five a second, per player
Each player has a bucket per channel: five tokens, refilling continuously. Spam past it drops and is reported as
Spam the bucket yourselfNet.RateLimited. Punishment is the game's call.4 of 5 tokens left. One second of quiet refills it.
~58 ns TokenBucket:take
- 05 / 08
No validator, no entry
A channel without a validator rejects everything. This one declares
Fail-closedRange = { 1, 500 }, run before any game rule. Rejections are silent: a probing client learns nothing.- Argument 1 in 1 to 500 42
- Argument 1 in 1 to 500 9001
~148 ns Hooks:fire with three validators; the Range rule is one of them
- 06 / 08
Game rules, in order
Game validators on
HooksIntent.Buyrun by priority.falserejects, and so does a validator that crashes.50Shop is open pass50Shop is open false100Can afford: 120 coins, price 25 pass
~148 ns the same hook chain; a crashing validator costs a rejection, not a server error
- 07 / 08
Written under a lock
The handler runs under
DataDriverpcall, takes the price from the server's catalog and writes the profile this server holds a lock on. It saves on the 60-second autosave or on leave.- Coins
12095- Owned
- { 7, 13, 42 }
- Lock
- this server, refreshed by every save
a table write now; the DataStore write waits for the 60 s autosave or the leave save
- 08 / 08
Every screen agrees
A Replica encodes the change once, 6 bytes, and sends the same frame to every subscriber. Nothing on this path polled: every hop was an event, a flush or a deadline.
Replica01fields01Coins5F95000000U32Coins95~270 ns delta encode, then up to 100 ms until the replica's next delivery at TickRate 10
Send your own
Press E or the button. Each press runs the pipeline's real rules against a wallet of 120 coins: a bucket of five a second, the Range rule and two hooks. Hold E to spam it.
Server work is the sum of the benchmarked hot paths on the way (bucket, decode, hook chain, Bus publish, delta encode): under 2 microseconds. What a player feels is heartbeat batching, the network and the replica's tick. Waits are drawn from the real limits: flushes at most every 1/60 s, replica deliveries at most every 100 ms.
The framework, layer by layer
Every documented module, grouped the way the sidebar groups them, from game-facing kits down to the kernel. Every line comes from a real require call.
In 0.9.1
Full changelog- DataLock handoff
Rejoins on the same or another server no longer wait or roll back. A crashed server's locks are taken in about 15 s.
- DataVersion history
Corrupt records restore from Roblox's own DataStore versions, and restoreAt stages an old version for review.
- CompliancePolicy, text filter and bans
Paid random items and trades wait on PolicyService, player text is filtered, and cheaters are banned through BanAsync.
- WorkspaceAgent-first workspace
AGENTS.md, a Game layer, scaffolding and one check command that runs every CI gate.
- TestingStudio spec gate
1,244 specs on every Play, an Output with only summary lines, and a gate plugins can drive.
- GameplayProjectile steering
Redirect a live shot, hand it to a new owner or retire it. Clients blend onto the new path.