Datastore backup question

Occasionally a game may have an update which messes with peoples data in an unintended way and as a result leads to players having data loss or some sort of corruption. Then as a response the game usually does a “rollback” where they set everyone’s data back to a previous date before the incident happened. My question is how do these games have their datastores set in a way they are able to do rollbacks like this?

For example, in my game I save timestamps to an ordered datastore which is essentially the key to the players actual data, similar to how datastore2 does it (I think). But I don’t actually have a good way to just simply rollback everyone’s data back to a certain point in time which basically makes this method useless for me. How do you guys accomplish this or how can this be done?

1 Like

I don’t know how datastore2 does it, but I’d setup my backups like this:
also, this is like half pseudo code since I’m on my phone

-- some date to roll back to and from
-- this could be stored in some datastore or hardcoded
rollback_day0 = some date and time where any saves before this time is rolled back
rollback_day1 = the date to roll back to

-- loads data after finding the date of the previous save
function load_data(some player id)
   -- this stores and sorts the dates that the player has saved data by the second or minute if you have some cache
   dates_datastore = datastoreService:GetOrderedDataStore(player's userid)

   -- this stores each rollback and the current data
   data_datastore = datastoreService:GetDataStore(player's userid)

   -- get the first page sorted descending so the first item is the most recent save
   pages = dates_datastore:GetSortedAsync(descending, 10)
   page = pages:GetCurrentPage()

   -- checks if there is any saved data
   if page[1] == nil then -- I havent used orderedDatastores in a while, not sure if this is right
      initialize the player's data, they're a new player
      return the new data
   end

   -- there is saved data, so we use the most recent date, page[1].key as the id in data_datastore as for the most recent save
   -- you could also use .value, but since we're using dates, the keys should be sorted anyways

   -- check if the most recent date is to be rolled back
   if page[1].key is before rollback_date0 then
      do some loop to check [2], [3], [4], ... etc until you find a date before rollback_date1
      if you're done with this page
         wait(some arbitrary time) -- so you don't use the datastore too fast
         page = pages:AdvanceToNextPageAsync()
         repeat whatever happened above
      end
      -- you'll probably want a better syntax, for that 👆, a while loop with a for loop inside might work
   end

   -- page[N] is the date you found that is before rollback_date1 or after rollback_date0
   data = data_datastore:GetAsync( page[N].key )
   return data
end


-- saves the new data in data_datastore as the current date
function save(some player id, data to save)
   today_date = get today or this week's date

   dates_datastore = datastoreService:GetOrderedDataStore(player's userid)
   data_datastore = datastoreService:GetDataStore(player's userid)

   previous_date = do what we did in load() to get the previous_date

   -- note, we're saving by the minute, so you can't just do == here
   -- maybe something like (date modulo seconds in a day) should work to get the day
   if today_date is the same day as previous_date then
      -- if today is a day with a save already
      don't do anything to dates_datastore since we'll be overwriting this save
   else
      -- if today is a day with no save, mark today in the ordered datastore
      dates_datastore:SetAsync(today_date, true)
   end

   -- save the data under today's date
   data_datastore:SetAsync(today_date, the data to save)
end
1 Like