Services
Available in: Server Only
This module runs exclusively on the server side. Use Signals or Client Methods to communicate with the client.
A Service is a ModuleScript created with Owl.CreateService() and loaded from ServerScriptService via Owl.AddServices() (see Installation). It's a singleton, there's exactly one instance of DataService for the lifetime of the server reachable from any other Service or from the client's Controllers.
Anatomy of a Service
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Owl = require(ReplicatedStorage.OwlKnit.Owl)
local DataService = Owl.CreateService({
Name = "DataService",
Dependencies = {}, -- > // Names of the Services this one depends on
Middleware = { -- > // Middleware specific to this Service (optional)
Inbound = {},
Outbound = {},
},
Client = {
-- > // Everything here is reachable from Controllers
PointsChanged = Owl.CreateSignal(),
State = Owl.CreateProperty("Menu"),
},
})
DataService._playerData = {}
function DataService:OwlInit()
-- > // Internal setup, fetching references to other Services
-- > // self.InventoryService = Owl.GetService("InventoryService")
end
function DataService:OwlStart()
-- > // Event connections, main logic
end
-- > // Automatic hooks
function DataService:OwlOnPlayerAdded(plr: Player)
self._playerData[plr.UserId] = { Points = 0 }
end
function DataService:OwlOnPlayerRemoving(plr: Player)
self._playerData[plr.UserId] = nil
end
-- > // Server method (callable from other Services via Owl.GetService)
function DataService:AddPoints(plr: Player, amount: number)
local data = self._playerData[plr.UserId]
if not data then return end
data.Points += amount
self.Client.PointsChanged:Fire(plr, data.Points)
self.Client.State:SetFor(plr, "InGame")
end
-- > // Client method (RemoteFunction, callable from a Controller)
-- > // The first argument is ALWAYS the calling player, injected by Owl.
function DataService.Client:GetMyPoints(plr: Player): number
-- > // Token check to confirm the player is properly registered
local token = Owl.GetPlrToken(plr)
if not token then return 0 end
local data = DataService._playerData[plr.UserId]
return data and data.Points or 0
end
return DataServiceOwl.CreateService options
| Key | Type | Required | Description |
|---|---|---|---|
Name |
string |
✅ | Unique identifier, used by Owl.GetService(Name) and in log output |
Dependencies |
{string} |
- | Other Service names this one needs initialized first - see Dependencies |
Middleware |
{Inbound, Outbound} |
- | Filters applied only to this Service's remotes - see Middleware |
Client |
table |
- | Signals, Properties and Client methods exposed to Controllers |
Server methods vs Client methods
Everything defined as function DataService:MethodName(...) is a server method callable from any other Service (typically after fetching it with Owl.GetService("DataService") inside OwlInit), never reachable from the client.
Everything defined inside the Client table or as function DataService.Client:MethodName(plr, ...) is exposed to Controllers as a RemoteFunction. Owl always injects the calling Player as the first argument automatically, you never pass it yourself when calling from the Controller side, see Client Methods.
Because any client can technically fire a RemoteFunction with a fabricated first argument in some setups, Owl also exposes
Owl.GetPlrToken(plr), a lightweight check confirmingplrreally is the player who made this specific call. Reach for it in any Client method that trustsplrto look up sensitive data, likeGetMyPointsabove.
Reading a Service's state from outside
Other Services call Owl.GetService("Name") server-only, resolved once during OwlInit and cached on self, never re-fetched on every call:
function InventoryService:OwlInit()
self.DataService = Owl:GetService("DataService")
endControllers never call Owl.GetService for anything other than reading Client members (Signals, Properties, Client methods), a Controller has no visibility into a Service's private state (self._playerData above) by design.
Where to go next
- Controllers - the client-side counterpart.
- Lifecycle - what
OwlInitandOwlStartactually guarantee and in what order. - Signals and Properties - the two ways a Service talks to its Client table.
- Automatic Hooks - the full list of hooks like
OwlOnPlayerAdded, beyond the two shown here.