Datastore Confusion

So i recently learned the basics of datastore (getasync(), setasync(), removeasync() ) but I’m not sure i understand fully. Are datastores automatically set to the player? like if i have a datastore key called “money”, does everyone have the same “money” value, once it is changed? So like i set the datastore key of money to value 50, do other players get this change too, or is it immediately set to my values?
Also, how do I see which datastores i created?

1 Like

What I think is that when you give a player a new datastore (yes, you DO have to make one for the player, they don’t automatically have one), the datastore is set to their UserId, meaning that if you change a player’s datastore, it only affects their values, as they only have one unique UserId per Roblox user. I don’t know if you can see their datastore specifically (in like a list is what I mean), but you can fetch some player’s datastore via scripts. I hope this was helpful to you!

1 Like

You’re misunderstanding keys here a bit, ideally in your data store the key should be the player’s ID (this will mean that this data is unique to that player), and the value should be a table of player’s data.
The table could look something like this:

{
["Money"] = 0,
["Level"] = 1
}

So if you for example need to change the money of a player, you change it in that table. And then use SetAsync where key is the player’s ID, and the value is that table.

Similarly, when the player joins, you can use GetAsync with their user ID, which will give you that table you saved previously.

1 Like

Also for seeing datastores you can use this free plugin.

1 Like

You can see it like this:
Datastore is a system which is not related with players at all, does not exist datastore per players or anything similar.

You create a datastore called Money. Now that is just a table an empty table, like this:
local Money = {}

Now you can save an index, whatever name you like:

local Money = {
	["wakamole"] = "hello"
}

You can use that for any purpose you like, like maybe the index name could be the userId of a player, and the value under that entry could be a number:

local Money = {
	[15346874984] = 50
}

Now you can add more keys to the table, using other player’s IDs, so now you have a table saved into a datastore that contains information related to whats money for you in your game.
You will search the key of the player you want to know its money, edit it, increase/decrease it. Add more userID keys to add more players, delete them etc.

local Money = {
	[15346874984] = 50, -- player 1
	[45618919] = 200, -- player 2
	-- etc
}

Now you can create a new datastore, you could call it Inventory, and same thing. Its not related to none players, its just a table and you choose what structure to use to build it as you need it. Simply information that you can save in order to handle mechanics in your game.


And there are plugins that lets you see the datastores in your game, I guess even edit them. I never used one, I prefer to do it proggramatically but, give it a check

1 Like

thanks for explaining it! it makes more sense now

2 Likes

Have in mind, that a whole datastore for only money, and another one for inventory could be a bad practice, cause you can nest tables, so the entry you are saving contains most of of player’s data.
I add more datastores only when I feel that the information I wanna save per entry, could eventually exceeds the max limit per key. Like idk, a game that lets a player to write a book. Any word they type will be saved meaning thousands of characters. If that amount of characters exceeds the limit per entry then it wont work.

But, if its just normal data of a player, like money, inventory, etc, you can merge everything into one datastore, “playersData”

2 Likes

can you store arrays/dictionaries inside datastores? like:

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local Mydatastore = DataStoreService:GetDataStore("TestDataStore")
local dictionaryInfo = {
["weaponID"] = 121 --id 121 would be sword
["weaponUpgradeLevel"] = 3
["weaponDurability"] = 88
["weaponSpecialUpgradeID"] = 213 --fire special
Players.PlayerRemoving:Connect(function(player)
Mydatastore:SetAsync(player.UserId, dictionaryInfo) -- the entire thing?
end)
}

these values are made up, its just for example

1 Like

Yes you can store tables inside tables into the datastore, as dictionary using indexes like that, just try it. If you see a warning check the structure of your table

2 Likes

when i print it, it gives me the whole table, but when i ask for a specific value, like:

print(Mydatastore:GetAsync(player.UserId[1]))--or
print(Mydatastore:GetAsync(player.UserId["weaponDurability"]))

it says “ServerScriptService.Script:12: attempt to index number with ‘weaponDurability’”
or “ServerScriptService.Script:12: attempt to index number with number”

You load the entire datastore with :GetAsync(), now hold that table and access the value you desire. You dont need to perform a :GetAsync() to get only one value. You should use it to load whole table.
I recommend storing the player’s datastore into a module table, so you can use it from there

module table? im not sure i understand

When you load the datastore key of a player, you can put that data into a table inside of a module script, so you have the whole information of that player in your server without needing to ask again the datastore data. The less you ask a datastore to save and load the better. Load it once, keep the data, work on that data when player does stuff, and save it when player leaves

1 Like

so i could make a module script that is a children of the a script, import the data then, and send it to the parent script?

Each time you require that module-script in another script, you are running the logic in that another script itself, not in that module.

So, I am not sure about this, but I don’t think there’s any way we can do to load the data once, put that into a module-script once the game began running already. Module-scripts have some limitations we have to consider here.

If we require a module-script, and put that data, we’re essentially doing it in that script itself, so that can’t be accessed if you require the same module-script from somewhere else, that’s my point.

If we are retrieving the dataStore in the module-script itself as well, then uh, what’s the difference? Since we’re still asking for that information when we’re requiring that module-script, we’re essentially still asking for the datastore data again. This approach wouldn’t be ideal because it would require multiple datastore calls, defeating the purpose of minimizing them.

By that, do you mean we can retrieve data once, and then when we require the module-script in a script, do you mean defining some functions that access the data you think all the data is retrieved and stored at?? Like, player’s cash value would be stored under that player, do you mean accessing that instead for convenience?

So, a single table within a server script is a great approach where you can handle all the things without having to ask for the datastore’s data again. Module-scripts are still useful for defining functions that manipulate player data stored in the server script table.

Sorry, I think we have a misunderstanding, probably I was not clear.

You have a server script which requires a module. The server script upon playerAdded perform the datastore call, the retrieved table will be stored in the module script, a table with all player’s data.

If all other server scripts require that module too they have access to the player’s data to be used and manipulated without doing any other datastore call.

So, if your server script loads player data from the datastore upon playerAdded event and stores it in a module script, subsequent calls to that module script from other server scripts won’t result in additional datastore calls because the data is already loaded and stored in the module script’s table

1 Like

I apologize for the misunderstanding. I initially thought data stored in a module script wouldn’t be accessible by other scripts. Your explanation clarifies that the data becomes a shared resource once loaded.

Thanks for clarifying, Dev_Peashie! I totally understand now how module scripts work as a shared resource for server scripts.

So, I ran a little test to solidify my understanding. I created an empty table in a module script and populated it with strings from one server script. Then, in another server script, I was able to access and print those strings, confirming the data persists within the module-script as well…

I also tested how script execution order affects the data a script retrieves from the module script. This way, I confirmed that the data is truly shared and persists within the module script itself.

I played with the timing like, putting 5 seconds in the Script 2, and 10 seconds in the Script 1 (and vice versa). Script 2 returned an empty table from that, whereas Script 1, since that’s where I populated the table with strings, returned a table of three strings, confirming the data is modified and persists within the module-script itself! (I tested vice versa)

ModuleScript:

local module = {something = {}}

return module

Script 1:

local moduleScript = require(script.Parent.ModuleScript)
moduleScript.something = {"Hello", "World", "Everyone"}

print("script 1:")
print(moduleScript.something)

Script 2:

wait(5)
local moduleScript = require(script.Parent.ModuleScript)

print("Script 2")
print(moduleScript.something)

Once again, thank you so much for the explanation.

Is there anything else we should consider when using this approach for player data management?

Is there a preferred way to handle situations where multiple server scripts might try to modify the player data in the module-script concurrently?

1 Like

Good testing! Yes, making sure how the data will load is key.

Any script that that requires the module you know it will yield until it get it.
If the data in the table of the module is extremely important to allow the player to start the game, would be better to be sure that all scripts that require the mainDataModule actually found data from the player, even if its an empty table.

Lets say that you have a dssLoader main script which is the first and only one that should add the table to the module. If that script takes longer to perform its task than other scripts (because dss network connection issues, and ofc it should retry until its sure it got a successful query) then all other scripts that requires the module should wait until finding that a player key is actually added into the module, otherwise they should wait.

The module could contain a table of “locks” that could let other scripts to wait until some tasks are finished.
Editing data in a module script from any other scripts its pretty fast, so, in common scenarios, many scripts trying to edit the data in a fast rhythm usually should not cause any issues (depending on the task, for example, increasing players money when they get a coin and there are many coins very close, on touch, works without issues, even if another script decrease the coins because idk, got hit by an enemy) those scripts are just accessing a value, and no matter which script chaged it before, still a constant value, so it will just perfom its task, decrease the value -= 1.

When the tasks are more sensitive, long, highresource consuming tasks, then yeah, find a way to yield, it highly depends on the system.


To me, its an efficient way to handle the player’s data, I end up with a core table which is easy to save and handle. I still think that each system would need a different approach based on the requirements. Like… too much data on module tables that needs to be send to client too thru remotes, could have a different approach if that data is updating constantly.

1 Like

You could make a server script that gets the datastore of the player and store it into a server module so you can handle that data from any server script. You can place that module as a children of the server script, or just in ServerScriptService.

Any of your server scripts systems that needs to work with that data, can require the module and have access to the data of the player to work with.
Like if you have a script that increases money, then require the module, change the value in the table of that player’s money.

When that player leave, take that player’s module table, save it into the datastore and flush the table (delete it) cause you dont need it anymore

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.