I find it inane that I’m getting throttled requests with ~120 players playing my game on all places while large Roblox games/places are able to handle data fine with little to no throttles - which is why I’m here to ask on how to improve my data saving methods.
The Set Up:
Four places
A main menu for selecting initial stats (faction and race)
A hub world for Faction A
A hub world for Faction B
A third place for other clashing purposes
One script in SSS handling data
Upon the player entering, os.time()-10 is set in a table so they avoid the same-key write/get limit (?)
Data is retrieved, if none is found then a template is saved; if it errors, save requests are blocked and nothing they earn saves
Every 30 seconds, if a player didn’t last save within 10 seconds or doesn’t have requests blocked, call UpdateAsync per player to save their data
When a player leaves, their data gets saved through the above method
I’m getting some hard throttles. What can I do to avoid them and actually be able to save player data appropriately? I refuse to believe that I’m hitting the budget/minute so quickly with so little.
There’s a debounce on the player manual save right? The limit per place is 60 + 10 * #players per minute and I don’t see how you could be saving 10+ times per player per minute unless people are spamming autosave.
One other optimization to consider would be only autosaving player data if there’s a change in data. Besides this you’ll probably have to track down the error yourself, it all seems perfectly normal to me.
Players can’t manually save. It retrieves their data when they enter and saves if they leave, provided they’ve been in the place instance for >10 seconds. Autosave can’t get spammed since it’s on server-side and is run every 30 seconds for >20 people per instance. Saving every time data changes will throttle me worse than what I’m getting hit with right now and that’s generally not a good practice.
I hate SetAsync. I only ever use it to set player data for those who are missing it or if I need their data overwritten by force. UpdateAsync respects their previous data, SetAsync does not. Given players are moving between places rather often, I can’t afford any cached, overwritten or improperly loaded data.
I’m going to try implementing GetRequestBudgetForRequestType and see if printing the budget to the console will help me figure out why my data throttles frequently. Perhaps I could even work with the returned number to work around throttled requests.
I’m not sure why my data throttles at all though. I don’t know of anything that can spend the budgets so quickly.
Calls used for Main Menu:
GetAsync: Used when a player joins to check for main, backup and menu data
SetAsync: Used when a player acknowledges that data from old builds doesn’t carry over to prevent message from showing up in future plays, completes all fields in the New Game center, has nil data or loads a backup (backup gets cleared after usage to prevent spam calls and such)
Calls used in all Game Places:
GetAsync: Used when a player joins
SetAsync: Used when a player joins with nil data (which no one should and therefore this doesn’t get called)
UpdateAsync: Used during an autosave cycle or when the player leaves; if they leave within 10 seconds of joining or an autosave cycle, UpdateAsync is not called and they lose what they gained during those 10 seconds
I notice that throttling begins normally during the autosave cycle due to mass prints of throttled requests. Atleast 20-30 players are on frequently, so I should have enough budget to be able to save and load properly. DataStoreService.AutomaticRetry is true for all places in the game.
Removing auto saving might fix my problem, however I think I should leave it in; I have disconnections, shut downs and failed save requests on player leaving in mind with auto saving, so their data isn’t outdated horribly when they return to the server.
If you are calling UpdateAsync every 10 seconds for autosave for every player, then you are calling it 6 times per minute per player. The limit for UpdateAsync is (30 + numPlayers * 5).
This means that if you have 20 players, your maximum number of allows requests will be (30 + 20 * 5) = 130.
You are calling UpdateAsync 6 times per minute per player, so you’re calling it 120 times.
However if you have more players, say, 30, then you will have 180 maximum requests. You are saving 6 times per minute per player. So now you’re calling UpdateAsync 180 times per minute.
See how the number of requests gets higher the more players you have? You’re using 6 requests per player which is higher than each player provides on their own, which is fine as long as the base number (30) can buffer it, but once you go above 30 players, you exceed the limit.
So like I said, if you are coding this the way I understand, you need to reduce the autosave interval.
I call UpdateAsync every 30 seconds for every player if UpdateAsync wasn’t called in the last 10 seconds for the player (time logged when they join or an autosave cycle runs). I’m pretty sure I made that clear already in the OP and several other posts.