Cross → Shared Memory

Shared Memory

A key-value store visible to every server simultaneously, backed by MemoryStoreService. All values are automatically JSON-encoded so you can store tables directly. Keys expire after a configurable TTL (default 1 hour).

All Memory methods yield — they make network calls to Roblox's MemoryStore infrastructure. Call them inside task.spawn or a coroutine if you don't want to block the calling thread.

Cross.Memory.Set()

Cross.Memory.Set(key, value, expiry?)

Write a value. expiry is in seconds — defaults to 3 600 (1 hour). Max 45 days.

local Cross = RoExpress.Cross

-- store a table
Cross.Memory.Set("event.config", { map = "Forest", duration = 120 })

-- store a number, expire in 5 minutes
Cross.Memory.Set("stats.kills", 0, 300)

-- store a flag
Cross.Memory.Set("maintenance", true)

Cross.Memory.Get()

Cross.Memory.Get(key) → value

Read a value. Returns nil if the key doesn't exist or has expired.

local config = Cross.Memory.Get("event.config")
if config then
    LoadMap(config.map)
end

local kills = Cross.Memory.Get("stats.kills") or 0

Cross.Memory.Update()

Cross.Memory.Update(key, transform, expiry?)

Atomic read-modify-write. transform receives the current value (or nil if the key is new) and returns the next value. Returning nil from transform deletes the key. This is the correct way to increment counters or append to lists — using Get/Set is not atomic.

-- safe global kill counter
Cross.Memory.Update("stats.kills", function(current)
    return (current or 0) + 1
end)

-- append to a list (cap at 100 entries)
Cross.Memory.Update("recentKills", function(list)
    list = list or {}
    table.insert(list, { killer = "Player1", time = os.time() })
    if #list > 100 then
        table.remove(list, 1)
    end
    return list
end, 3600)

-- delete a key by returning nil
Cross.Memory.Update("maintenance", function() return nil end)
Use Update for shared counters, not Get → Set. If two servers call Get, increment, and Set at the same time, one write is lost. Update is atomic — Roblox guarantees only one transform runs at a time per key.

Cross.Memory.Remove()

Cross.Memory.Remove(key)

Delete a key immediately. Equivalent to Update returning nil but slightly cheaper.

Cross.Memory.Remove("event.config")
Cross.Memory.Remove("maintenance")

Key naming

All Cross.Memory keys share one MemoryStore hash map ("rx:mem"). Use dot-separated namespaces to avoid collisions between different systems:

PatternExample
module.key"stats.kills", "stats.deaths"
event.id"event.active", "event.map"
player.userId"ban.12345"

See also

← Cross  ·  Messaging | real-time events across servers  ·  Server Registry | discover live servers