Port → Creating Ports

Creating Ports

Call app:Listen(name, callback, settings?) to register a named port. The callback receives the port's own App-like instance — a fully isolated pipeline with its own RemoteEvent, Router, and TokenBucket.

Signature

app:Listen(name: string, callback: (port) → (), settings?: PortSettings) → Port
ParameterTypeDescription
namestringUnique port identifier — must match the name used on the client
callback(port) → ()Called immediately with the port instance. Register routes inside.
settingsPortSettings?Optional TokenBucket configuration (see Port Settings)

Port API

The port instance exposes the same routing interface as App:

port:Get(route, handler)
port:Post(route, handler)
port:Put(route, handler)
port:Delete(route, handler)
port:Use(id, fn)  ·  port:Unuse(id)
port:Push(player, event, data)  ·  port:PushAll(event, data)  ·  port:PushTo(players, event, data)

Combat port example

local RoExpress = require(game.ReplicatedStorage.RoExpress)
local app = RoExpress.GetApp()

app:Listen("combat", function(port)
    port:Post("shoot/:targetId=number", function(req, res)
        res:Send(handleShoot(req.player, req.params.targetId))
    end)

    port:Post("reload", function(req, res)
        res:Send(handleReload(req.player))
    end)
end, {
    maxTokens  = 20,
    refillRate = 10,
})

Getting a port reference later

If you need to add routes or call push methods from outside the Listen callback, use app:GetPort(name).

app:GetPort(name: string) → Port
local combatPort = app:GetPort("combat")
combatPort:Get("status", function(req, res)
    res:Send("ok")
end)
Isolation. Each port creates its own RemoteEvent in ReplicatedStorage under a name derived from the port name. Requests to the "combat" port never share bandwidth or rate-limit tokens with the main App channel or other ports.

See also

← Port  ·  Using Ports | client-side access  ·  Port Settings | TokenBucket configuration  ·  Router | route syntax available inside ports  ·  Gun Example | combat port in full context