Best way to store player data?

Hey!
Just got back into making games on Roblox after a two-year break. Feeling a bit rusty and overwhelmed by all the new features in Roblox Studio.
I’m wondering if there’s a better way to store player data now. I’m planning a game that needs to handle a lot of data, and I’m not sure if sticking to bools, strings, and ints is still the best approach, like i used to do.

I’m thinking about using this script I found from my previous games, but I’m not sure if it’s the best idea.
Any help is appreciated, thanks!

stats script
local DataStoreSettings = require(script:WaitForChild("Settings"));
local DataStoreModule = require(script:WaitForChild("DataStore"));

local StatsData = game:GetService("DataStoreService"):GetDataStore(DataStoreSettings.DataStore.StatsDataStore);
local GameType = game:GetService("RunService"):IsStudio();

local statList = {
	{"lastPosition","Vector3Value",Vector3.new(0,0,0)};
	{"level","IntValue",1};
	{"exp","IntValue",1};
	{"strength","IntValue",1};
	{"agility","IntValue",1};
	{"endurance","IntValue",1};
	{"age","IntValue",1};
}
--[[
	"level", -- Value Name
	"IntValue", -- Value Type
	1, -- Default Value
--]]

function PlayerAdded(Player)
	local statsfolder = Instance.new("value");
	statsfolder.Name = "stats";
	statsfolder.Parent = Player;
	
	for i,v in next,statList do
		local Value = Instance.new(v[2]);
		Value.Name = v[1];
		Value.Value = v[3];
		Value.Parent = statsfolder;
	end
	
	DataStoreModule.LoadData(Player,statsfolder,StatsData);
end

function PlayerLeft(Player)
	local err,done = pcall(function()
		StatsData:SetAsync(Player.UserId,DataStoreModule.SaveData(Player.statsfolder));
	end)

	if (GameType == false) then
		game:GetService("TeleportService"):Teleport(game.PlaceId,Player);
	end
end

if (GameType == false) then
	game:BindToClose(function()
		for i,v in next,game.Players:GetPlayers() do
			PlayerLeft(v);
		end
	end)
end

game.Players.PlayerRemoving:Connect(PlayerLeft);
game.Players.PlayerAdded:Connect(PlayerAdded);