How many datastores allowed per game

Hello! I want to know how many datastores can a game have because the dev hub does not say anything about it. In other words, it is how many local DataStore = game:GetService("DataStoreService"):GetDataStore("Datas") can I have because my I have lots of inventory-systems in my game and there were lots of dataloss. I want to make it kinda like this instead:

--when player leaves
game:GetService("DataStoreService"):GetDataStore(tostring(player.UserId)):SetAsync(PlayerDatas)

So every single player has his/her own datastore and it will be better. But there might be a limit so I want to know how many local DataStore = game:GetService("DataStoreService"):GetDataStore("Datas") can a game have. Please answer me if you know! Thank you!

3 Likes

Datastore keys are technically infinite to my knowledge though I’d like to correct how you are saving your data as it’s not right. Hopefully this helps.

local DataStoreService = game:GetService("DataStoreService") --Define the service
local Datastore = DataStoreService:GetDataStore("PlayerData") --Create our datastore

Datastore:GetAsync(Player.UserId, Data) --Load data from player id
Datastore:SetAsync(Player.UserId, Data) --Save data to player id

I can make a full datastore example if you like.

You don’t create a new datastore for each player. You create a single datastore then save each player to their own key.

2 Likes

Yes, that is how it is working right now. But there are datalosses for my inventory system. Maybe it’s my own code that is the problem because other data like coins, gems, etc. never had dataloss. Can you help? Here is code:

–In the player added function

wait(1)
local SpellInv = nil
for i = 1, 10 do
	if SpellInv == nil then
		invData:GetAsync(userId.."SpellInv")
	end
	wait()
end
if SpellInv then
	coroutine.resume(coroutine.create(function()
		for i, spellName in pairs (SpellInv)do
			local stringValue = Instance.new("StringValue")
			stringValue.Name = spellName
			stringValue.Parent = player.SpellInventory
			wait(0.1)
		end
	end))
else
	print("NO SPELL INV")
end

And the saving part:

local inventory = {}
for i, v in pairs (player.SpellInventory:GetChildren()) do
	table.insert(inventory,v.Name)
end
local success, errorMessage = pcall(function()
	invData:SetAsync(userId.."SpellInv",inventory)
end)
if not success then
	print(errorMessage)
	saveData(player)
end

Please help!!

I’ll try my best to create my own datastore for your system. Pretty sure your losing data when your requesting it. I’ll reply once done and I’ll make to comment it for you to understand.

I think you should give this a read.

Specifically the bottom section where it says “Create Fewer Data Stores”

--Setup
local DataStoreService = game:GetService("DataStoreService") --Define the service
local Datastore = DataStoreService:GetDataStore("Spells") --Create a datastore for spells

local DataCache = {} --Create a cache for our data so we can use it later

--Loading data when a player joins
game.Players.PlayerAdded:Connect(function(Player) --Player joins the game
	local Success, Data = pcall(function() --Run a pcall to catch errors
		return Datastore:GetAsync(Player.UserId) --Get the players data
	end)
	
	if Success then --Check if getting the data worked
		--If it did work lets continue and check if the player has data
		if not Data then --Check if they are a new player
			--New player so let's create them data
			--I recommend switching to tables instead in string values cause you can add more things in one datastore like so:
			Data = {
				Coins = 100,
				Level = 1,
				Spells = {"Fire", "Water"}
			}
		end
		DataCache[Player.Name] = Data --Asign their data to the cache
	else
		--If it didn't work you could have another attempt if you set it up that way
		--For now we are just going to kick the player
		Player:Kick("Error loading data")
	end
end)

--Now for example we want to update the players data we can do:
DataCache[Player.Name].Coins = 1000 --Set their coins to 1000
--Or we want to add a spell we can do:
table.insert(DataCache[Player.Name].Spells, "Ice") --Add ice spell to spells.
--Or we can read each spell
for i, Spell in pairs(DataCache[Player.Name].Spells) do
	print(Spell) --Fire
end

--Saving data now
game.Players.PlayerRemoving:Connect(function(Player) --Player leaving the game
	Datastore:SetAsync(Player.UserId, DataCache[Player.Name]) --Save their data
	DataCache[Player.Name] = nil --Remove their data from the cache as it's no longer needed
end)

I’ve replied to my own post with a full datastore system and commented what each thing is doing. Hopefully it helps.

1 Like

I can see the logic, and i think the key difference is that i have a folder inside the player instance, containing their spells because i need to access their inventory from other scripts and local scripts too. Is there a way you can convert the code into using a folder instance in the player? Thank you!

I’ve provided you the to a datastore system so you should be able tweak it and switch to using a folder with string values but it’s generally a bad practice or bad way to doing things. You should really look into setting up Remote Functions to request the data when the client needs it. if you really really, really wan’t to use StringValues then I recommend the new Attributes instead.

For example:

image

Server

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")

Remotes.RequestData.OnServerInvoke = function(Player)
	return DataCache[Player.Name]
end

Client

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")

local Data = Remotes.RequestData:InvokeServer()
print(Data.Spells) --Prints spells
1 Like

Ok. But is there a way to save dictionary into object? Because there isn’t a DictionaryValue object so how do i do this? I won’t place it as descendant of the player tho

EDIT:
Oh yes that might be a way. I will try it out :slight_smile: thanks

EDIT 2:
How do i use bindable functions for this as well because i sometimes need it from another server script

I’m trying to tell you that saving the data physically with the use of Values or Attributes isn’t a very good way. The one environment I can see using physical representations of values would be like leaderstats with coins for example.

EDIT 2 Reply:
I’ve actually personally never used bindable functions so I have no say on them, sorry.

1 Like

technically, you could create as many as you want, unless you make roblox servers crash, then maybe not

1 Like

oh, bindable events are really just remote events BUT you use bindableEvent:Fire() and bindableEvent.OnEvent:Connect(function()).

ok, i will take the advise :slight_smile: thx bro

There’s a dedicated section in the documentation page for DataStores named “Limits” which goes over the various limitations imposed on DataStores, such as the key length, value length etc.

Component Maximum Number of Characters
Key 50
Name 50
Scope 50
Data 4,000,000

If I use the way @alphajpeg suggested, it would reach the datastore limit pretty fast. So I was thinking of making one datastore for each player so they can’t reach the 4 million characters limit. Is it good performance?

4 million characters is way more data then you should need to store per player, almost ever. If you find yourself reaching that limit, you should reconsider how you save data.

Edit (11/12):
The only exception is unlimited builds which can take up infinite space, in which case it might be feasible to store them separately. If you do not have this and find yourself reaching the limit, there are likely better ways for you to store your data. See example below.

For example, if you were storing crates inventory,

{
    {
        Type = "Legendary",
    },
    {
        Type = "Legendary",
    },
    {
        Type = "Legendary",
    },
    {
        Type = "Legendary",
    },
}

is less efficient than:

{
   Legendary = 4
}

Even better, you can use ids instead of a whole string

{
   [1] = 4
}

The point is: being mindful of how you store data is just as important as what you store.

Um… i think u misunderstood. What I mean is, each datastore has a limit of 4 million characters. So, if I do what @alphajpeg suggested, which is storing everything in one datastore, it will be filled pretty quick. But my idea is to make a datastore for EACH player, so its kinda like this

local dict = {
    cash = player.Cash.Value
    level = player.Level.Value
}
game:GetService("DataStoreService"):GetDataStore(tostring(player.UserId)):SetAsync("Datas",dict)

So every player has his own datastore. The point is so that the limit of 4 mil characters would never be reached. I don’t want dataloss so I think this might be a good way. It is quite impossible for a single player’s data to reach 4 mil characters so it will never fill. But, if I use @alphajpeg way, which is storing every player’s every data into one datastore, it will probably fill up really quick. But creating tons of datastore for each player might also not be good. So what should I do?

  1. One datastore for one player every data

OR

  1. One datastore for every player every data

Please help

You’ve misread the limitations.

Each key within a datastore has a limit of 4 million characters. (Source)

There is no limit of data storage related to datastore or scope, only the key. (There is a limit on scope and datastore name length, but that doesn’t affect data storage)

Since GetDataStore is ratelimited, you can save yourself the hassle by storing all of your data in one datastore, and using a player’s UserId as the key.

Example:

local datastore = DataStoreService:GetDataStore("PlayerData")

--in some playeradded event or some other event
local fetchedData = datastore:GetAsync(player.UserId)
--saving
datastore:SetAsync(player.UserId, data)

Source:
Datastore Limits

OOOOOOOOOOOHHHHH THANK YOU SO MUCH I think I figured out the problem because I have like 5 Datastore and I use GetAsync like 10 to 20 times when player leave and join. Also, I store their data as values inside the player instance so both of these factors might have lead to the data losses. By the way, how do I use Datastore2 to store a dictionary? I can’t understand the article so can u give me an example of saving and loading a dictionary with Datastore2 please? Thank you!