Datastore Data Migration for Easier Updates and Less Data Wipes!

Hello! I recently made a datastore data migration system, and noticed that there was only one post about it, and the methods used were just a little too messy!
And it would it super helpful for new or existing games to do small or massive updates and changes with this system, hope it helps!

Note that I expect you have some decent knowledge of Luau, as I won’t be explaining much, and this is pretty much just a showcase showing the general idea of how it works!

The main idea: If a player with datastore version 2 joins, and the server’s datastore version is 5, it’ll migrate his data to version 3, 4, then 5!

These are the main functions:

local serverDsVersion = 2

local DataMigrationFunctions = {
	[1] = function(data)--migrate to version 1
		--change the data to the new version
		return data
	end,
	[2] = function(data)--migrate to version 2
		--change the data to the new version
		return data
	end,
}

local function MigrateData(data)
	if data.DsVersion < serverDsVersion then--check if his data needs updating!
		for i = data.DsVersion+1, serverDsVersion do
		--^^^ iterate through all the versions from his version to the server's version
			data = DataMigrationFunctions[i](data)--migrate the data
		end
		data.DsVersion = serverDsVersion--set the new datastore version
	end
	return data
end

Use Summary:

The serverDsVersion variable dictates the current datastore version of the server, the starting version should be 0, and remember to change it by +1 when you release a new migration!

In the DataMigrationFunctions array, the index is the version it will migrate to, and the value will be the function that changes the data, it takes the datastore’s saved data as an argument, then you do your cool changes to the data, then return the new migrated data at the end.

The DataMigrationFunctions table needs to be an array! So no skipping numbers or any non-numerical indexes! I’m setting the indexes, as the version number is more clear, but if you just wanna use comments, go ahead!

Use Example: In the following code, version 1 adds an inventory, and version 2 add a starting item in that inventory!

local serverDsVersion = 2

local pys = game:GetService("Players")
local dss = game:GetService("DataStoreService")
local plrDataDs = dss:GetDataStore("PlrData")

local DataMigrationFunctions = {
	[1] = function(data)--migrate to version 1
		data.Inventory = {}
		return data
	end,
	[2] = function(data)--migrate to version 2
		--Lets assume the item ID is 6, let's take into account if they already have that item aswell!
		if data.Inventory["6"] then
			data.Inventory["6"] += 1
		else
			data.Inventory["6"] = 1
		end
		return data
	end,
}

local function MigrateData(plr, data)
	if data.DsVersion < serverDsVersion then
		for i = data.DsVersion+1, serverDsVersion do
			data = DataMigrationFunctions[i](data)
		end
		data.DsVersion = serverDsVersion
	end
	return data
end

local function PlrAdded(plr)
	local success, data = pcall(function()
		return plrDataDs:GetAsync(plr.UserId)
	end)
	if success then
		if data then
			data = Migrate(data)
		else
			--Set the default data however your game does it!
		end
	end
end)

pys.PlayerAdded:Connect(PlrAdded)
20 Likes

amazing resource, UncertainLeo !