Best way to use DataStore?

I’m about to start work on a new project; and I was wondering what the best way to use DataStore is?

Whenever I use value.Changed to save, the datastore stops working and I get data loss complaints from players.

What other ways are there to trigger the saving of data? Should I try using a p-call and a retry function?

DataStores have limits and you should not be saving data each time a value changes.

Try saving on PlayerRemoving and game:BindToClose()

Here’s a good post by @sjr04 about when to save data.

Edit :

@Winky_y

No, in case of DataStore errors or poor connectivity, requests to DataStores can fail; that’s the reason wrapping them in protected calls is ideal for preventing Data loss, you can use them to retry saving data if an error was encountered.

2 Likes

Does PlayerRemoving account for players disconnecting?

That’s the one purpose for PlayerRemoving.

By disconnecting I mean if their internet cuts out or something.

Yes, the event fires whenever a Player is removed from Players.

I just want to clarify that if a player’s data is having errors saving you shouldn’t just keep retrying to infinite times. It’s best to only retry up to 5 times because then you end up running into DataStore limits and more than just one player will be losing data. If you want to get advanced you could use external programs to store/track failed save data.

Why not retry infinite?(30 charsssssssssss)

Because a script could quickly max your DataStore limits if you let it retry over and over for infinite times.

Alright, so you have to understand that DataStore have a limit on how many times it can save some data.
It is recommended that you save the data each 5 minutes, when big actions are done(like removing or adding a huge amount of money, etc), and when the player leaves. You should also use game:BindToClose! game:BindToClose is just when the server shutdowns. Also, try to use UpdateAsync over SetAsync! I suggest you loop up some tutorials to make sure you used those events correctly.

I wouldn’t save data every X minutes. Don’t do this But saving data when a player buys a developer product is a good point.

You should auto save data for all players at regular intervals too, this can prevent potential errors while saving data at other places such as PlayerRemoving.

This is also suggested on the Developer Hub

It really depends on what you are saving and some errors could come up. If it is just the money/points, then sure we could save only when there is a change to those value, but some errors might pop-up. But if it would be some other values that would change in 5 seconds (like a Simulator with a map saving), then saving each 5 minutes would be better than saving each time a part is added.

Its always better to be safe than sorry as it is not really funny loosing some data.

Keep in mind that you only have 30 seconds with game:BindToClose(), so you shouldn’t rely on that heavily if you have a lot of data to save. Saving at regular intervals, when a player leaves, OR on BindToClose (if either of those 2 fail) is the best way to do it imo.

I guess it all comes down to how often you save data and what kind of data you’re saving.

Use coroutines for game:BindToClose().

That won’t help. Only 1 coroutine ever runs at once, which means they’ll all run one at a time anyways.

Proof: coroutine.running() only ever returns 1 thread.

What is the difference between updateasync and setasync?

Update gives you the current table through an argument in it’s function so you can use that to “update” the value instead of reset it to something else.

local success, result = = pcall(function()
    playerStore:UpdateAsync(player.UserId, function(currentData)
        local data = currentData or {}
        data[key] = newValue
        return data
    end)
end)

This is handy if you only need to save on value in a table that’s being saved, and you don’t have the current table handy. It prevents you from having to do GetAsync() to get the table and then set it using SetAsync().