Instance Values vs Modules for Data

Hey Dev Forum.

Ive been battling this for a while now and I wanted to get some opinions on this.

For my new game I want a secure way to store and hold data. I want a easy way to access these values, change these values, and see when these values changes to update GUI’S ( Money counters , Stats Counters etc etc)

Ive been researching things like Profile Service and DataStore2 and I was wondering if I should use Modules for my Data instead of the regular Instance Values used.

For a while now I’ve been using Instance values in folders on the server for my data which i feel a bit more comfortable using and I’m worried this isn’t the most secure way.

I just want to know if I should continue using the Instance Values or switch to modules

Thanks!

( The way i traditionally data store below)

local DSS = game:GetService("DataStoreService")
local PlayerData = DSS:GetDataStore("RaceData001")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")

local function CreateTable(Plr)
	local PlrStats = {}
	for _,V in ipairs(Plr.RData:GetChildren()) do 
		PlrStats[V.Name] = V.Value
	end
	return PlrStats
end

local function Save(Plr)
	local PlrStats = CreateTable(Plr)
	local Sucess, Error = pcall(function()
		local PlrUserID = "Player_"..Plr.UserId
		PlayerData:SetAsync(PlrUserID, PlrStats)
	end)
	print("Attempted to saved player please wait for data response")
	if not Sucess then 
		warn("Not Able To Save")
		
	else 
		print("Sucessfully Saved "..Plr.Name)
	end
end

Players.PlayerAdded:Connect(function(Plr)
	local RData = Instance.new("Folder", Plr)
	RData.Name = "RData"

	local RaceRolls = Instance.new("IntValue")
	RaceRolls.Parent = RData
	RaceRolls.Name = "RaceRolls"
	RaceRolls.Value = 5
	
	local Race = Instance.new("StringValue")
	Race.Parent = RData
	Race.Name = "RaceData"
	Race.Value = "Human"

	

	local PlrUserId = "Player_"..Plr.UserId
	local StoreData 
	local Sucess, Error = pcall(function()
		StoreData = PlayerData:GetAsync(PlrUserId)
	end)
	if not Sucess then 
		warn("Not Able To Save")
	end

	if type(StoreData) == "table" then
		for I,V in pairs(StoreData) do
			if RData:FindFirstChild(I) then
				RData:FindFirstChild(I).Value = V
			end
		end
	end
end)

Players.PlayerRemoving:Connect(function(Plr)
	Save(Plr)
end)

game:BindToClose(function()
	for _, Plr in ipairs(Players:GetPlayers()) do
		Save(Plr)
	end
end)
2 Likes

its up to you. I store all my data in a table. It just makes more sense to me if i store data in a table vs instance values.

I recommend keeping a table in a module on the server for reference and data-checking, and then if you want you can either use attributes for reading the data globally or have a function in a module that returns a read-only copy of the main table. I recommend not using InstanceValues at all, and swapping them out for attributes instead as InstanceValues are deprected/superseded.
Edit: Here’s the link for info about Instance Attributes.

Intresting can you show me a code sample of how I would accomplish this?

Just to be clear if i dont use the method you suggested anduse my method theirs a higher chance of my data getting hacked or it being easily manipulated? The problem for me is not learning a new way of datastore its just I want something that’s secure. So specifically would the way I’m using be less safe than the one you proposed?

Well, it’s not about the methods you use, but the way you use them. As long as the data is read-only for the client, it’s secure as can be. If a client tries to edit the value of an InstanceValue or an Attribute, it won’t replicate to the server. However, if you make a function that edits the main data table in a module, make sure there’s no way a client can run it via a remote event.