What is the best approach to storing players in the Memory Store?

I’m starting the implementation of user status that will be consulted by servers.
For example, if the user is online in the game or not, if he has an open frame or not, etc.
For that, I’m thinking about using the new service Memory Stores | Roblox Creator Documentation with Sorted Maps.

Initially, I thought of having only 1 sorted map containing a dictionary with all the UserIds and inside each UserId key, the users’ necessary data:

local SMUserStatus = MemoryService:GetSortedMap("UserStatus") -- SM = "Sorted Map"

But this way, every time I want to query the status of a specific user, I have to reload the ENTIRE user’s table:

function GetUserStatus(UserId)
	local UserStatus = SMUserStatus:GetAsync(UserId) or {} -- load ALL users
	return UserStatus 
end

I think this may exceed some quota limit and run into some slow reading.

So I thought if I should create a separate Sorted Map for each UserId:

function GetUserStatus(UserId)
	local SMUserStatus = MemoryService:GetSortedMap("UserStatus" .. UserId) 
	local UserData = SMUserStatus:GetAsync(UserData) or {}
	return UserData-- get specific user data
end

But in the case above I’m worried that this will slow everything down since I’ll have to run a MemoryService:GetSortedMap on every query, in addition to GetAsync

  1. What would be the best approach? A single dictionary with all players to use a single Sorted Map or multiple Sorted Map, one for each UserId?
  2. If I have a single map, how can I read all the keys, where GetAsync only reads 1 key and MemoryStoreSortedMap | Roblox Creator Documentation is limited to 200 keys?

is the problem that you need to call GetAsync for each function call? I’m not sure how the second method would help avoid the quota, since it is shared between memory tables.

you have at least 100 calls available to you per player, per minute. I doubt you should worry about a quota unless you are using even more memory tables somewhere else. you’re not binding this to render step. well, I hope not anyhow :slightly_smiling_face:

if speed is a problem, you can also just have a loop outside to call GetAsync every x seconds and cache it in an outer scoped variable. then return the latest value from the function.

with regards to the second question, you need two nested loops. one calls GetRangeAsync with an upper bound of 0, 200, 400… and the other iterates those tables, essentially piecing them together.

1 Like

You can just cache the data, and reload it every, say, 30 seconds.

1 Like