How to use DataStore2 - Data Store caching and data loss prevention

I’m certain I’m saving it because I rejoin the game and it loads all my data and then when I teleport to a place inside of the game it doesn’t load the data?!?!

DO you have the same datastore in all places with the same values and masterkey?

yea apart from masterkey cus like do i even need it

Hello! I currently use this for my game! Is this going to update this to work with DataStore v2?

1 Like

Is there a way to change a specific player’s values if the player is not in the game?

Will you make any updates after this release from Roblox?

2 Likes

Yeah ok I added masterkey and I still couldn’t get it to work

Try removing the ‘Datastore2.Combine’ part of the script and seeing if that makes it save between games. It worked for me for some reason

1 Like

For anyone who also uses the DataStores2 module, we were wondering if anyone else has had this similar issue and if they were able to figure it out. On very rare occasions (1-2 reports a day with 300-500+ ccu) players would lose their data from their last played session. It would usually become apparent when they rejoin and lose a sum of points, levels, etc, but the data usually is never fully wiped. We use Ordered Backups (berezaa method) which is likely why it’s not completely gone when this happens, but we’ve been pretty stuck as far as why this is happening in general. Also unsure if this could be a result of the new Datastores V2 update, since I have yet been able to figure out any potential reason from our end.

2 Likes

Okay so it looks like I made a rookie mistake and that’s why I couldn’t get it to work. I’ve fixed it now. Thanks for help!

Before releasing the game I would like to wipe the data for all tester players.
I checked the API but could not find a function for that.

I bet this is done somehow super easily, but how?
How do you start with a blank datastore again?

Thanks in advance for any guidance on what I should try!

edit:
I was thinking about this and realized the way to start fresh is simply to change the masterKey, right!?

DataStore2.Combine(masterKey, ...keysToCombine)

Please confirm this is the way to do it.

edit2:
Yes, that works. Thanks! :slight_smile:

Having a similar issue. Did you ever resolve it?

I noticed that it prints in the output “player left, saved (key)” even though it isn’t actually saving in studio because of the setting. It still warns “Data store (key) attempted to save in studio while SaveInStudio is false.” before this but I’m pretty sure it’s not supposed to say it saved in this case. Is this a known bug?

It’s known, yes. Ideally it wouldn’t spit out logs like that at all.

Alright thank you.

I can’t understand how a lot of the scripts work but if it works it works and I’m okay with that.
Possible fix in a future update maybe?

Anyways, I have an actual question as well.
What would the best way to save a massive changing table be? Like saving something like items in an inventory with the system. I’m probably overthinking it but I want to have some examples to compare with.

Right now I just have it so that it gets the data, inserts the new thing in the table and sets the data to that but I’m wondering if there’s a more secure way or quicker way to do this?

This isn’t actually bad, it’s fine, it gets the job done.
I only advise changing it if you’re changing values frequently.

As you might have noticed already, DataStore2 ends up deep copying values passed through :Set functions, etc.
I (believe) this is the case with :Get too

If so, then you should also know that you can connect a handler function to run before the data is saved, using :BeforeSave.

What you can do, is, if you have a reference of your weapons as your main thing, that you edit, then you can defer these changes. Only :Set'ing on :BeforeSave, I haven’t personally used DS2 like that, but I would guess something like this would work:

local InventoryData = {
    -- [player] = {"ItemID1", "ItemID2"}
}

--- On Data Loading:

local inventoryStore = DataStore2(player, "Inventory")

InventoryData[player] = inventoryStore:Get({})

inventoryStore:BeforeSave(function()
    inventoryStore:Set(
        InventoryData[player]
    )
end)

Problems with this:

  • When using :Get you’re not ensured at all that it will give you an updated version of the inventory data, you will need to handle sharing that between scripts yourself if you need to.

Like I said, the solution you were doing is just fine if you’re only modifying data here and there, stay with it if that’s the case.

If you’re changing values constantly, like things like every frame or close to it, this is probably worth the trade-off.

Ah thank you.
Any guidance, advice, and input helps me a lot. Knowing how on track I am really helps me keep moving.

Don’t think frequency will be a concern in my case since the only values I’m saving this way are either really infrequently changed or limited with a timer for user input.

Besides the basic ones, I haven’t quite been able to understand how most of the functions work or when I should use them in more complex systems and situations but I’ll look into it, definitely.

1 Like

Will new data saving methods be added to your module? For example, an official caching save method has recently been added.

Probably not, I have plans to make something more specialized for me. I think DataStore2 is in a fine place as is.

My datastore script is working and it output [Player left, saved DATA],
but when i rejoin the game the data is not saved.

my API services is enabled, and its not in studio.
Data script:

local DataStore2 = require(game.ServerScriptService.DataStore2)
DataStore2.Combine("DATA", "Clicks", "Diamonds", "Rebirths")


game.Players.PlayerAdded:Connect(function(player)
	local clicksDataStore = DataStore2("Clicks", player)
	local diamondsDataStore = DataStore2("Diamonds", player)
	local rebirthsDataStore = DataStore2("Rebirths", player)
	
	
	
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local clicks = Instance.new("IntValue")
	clicks.Name = "Clicks"
	clicks.Parent = leaderstats

	local diamonds = Instance.new("IntValue")
	diamonds.Name = "Diamonds" 
	diamonds.Parent = leaderstats

	local rebirths = Instance.new("IntValue")
	rebirths.Name = "Rebirths"
	rebirths.Parent = leaderstats
	
	
	if clicksDataStore:Get() ~= nil then
		clicks.Value = clicksDataStore:Get()
	else
		clicks.Value = 0
	end
	if diamondsDataStore:Get() ~= nil then
		diamonds.Value = diamondsDataStore:Get()
	else
		diamonds.Value = 100
	end
	if rebirthsDataStore:Get() ~= nil then
		rebirths.Value = rebirthsDataStore:Get()
	else
		rebirths.Value = 0
	end
	
	
	clicks.Changed:Connect(function(player)
		clicksDataStore:Set(clicks.Value)
	end)
	diamonds.Changed:Connect(function(player)
		diamondsDataStore:Set(diamonds.Value)
	end)
	rebirths.Changed:Connect(function(player)
		rebirthsDataStore:Set(rebirths.Value)
	end)
end)