Why isn't my data saving on shutdown?

Is it necessary to use coroutines in this case to yield? I didn’t know this function existed until reading your thread, and when I went to the DevHub to look into it further, they give a very similar example of BindToClose but without any sort of yielding. Just want to make sure my players’ data won’t get erased if I don’t yield inside this function.

The DataModel:BindToClose() documentation has this comment in the example:

SetAsync yields so will stall shutdown

This tells me that yielding is an important thing to do to prevent shutdown from happening while you’re still saving, and that SetAsync function call is where the yielding happens in that example. However,
that example has the same pitfall as a couple of the posts in this thread that I’ve mentioned before, where saves happen in series rather than in parallel.

For that reason, I think the example in the docs is not a good example unless you’re only saving 1 player’s data. It’s definitely important to yield in BindToClose (which they do) and it’s also important to handle them in parallel (which they don’t).

There’s another bit in that documentation that stands out to me:

Bound functions will be called in parallel, meaning they will run at the same time.

This is really useful behavior. The examples I posted above follow this behavior:

  • Bind a handler to close that runs once and saves all players data, spawning a new thread for each

However, an alternative is to call BindToClose for each player. That operates like so:

  • Bind multiple handlers (one for each player) that each run once and save only that one player’s data

This lets the engine start the threads for you. I haven’t done it this way before, but I don’t see why it wouldn’t work. You may want to verify the player is still in the game before saving their data, since I’m not aware of any UnbindFromClose() function or similar.

You should be saving player data in three places:

  1. On PlayerRemoving event
  2. On BindToClose event
  3. On an interval, in case the server crashes and those events don’t fire to mitigate data loss

There’s no way with DataStore to fully prevent all data loss if your data changes frequently, there’s always potential they do something between the last interval save and when the server crashes. This is an unavoidable data loss scenario, but with interval saves, you can reduce the amount of time that the data had to change.

It’s also possible data store service takes too long to save data, for example if it takes longer than 30 seconds, the BindToClose() function times out anyway, server shuts down, and the data saving never gets to finish.

1 Like

From what I understand BindToClose only fires when the very last person is exiting the server.
The problem is trying to cram all them saves in BindToClose or a remove function. If you saved each player as they exited that itself should be enough. Not the entire server just the one that logged off. Why everyone is looking to save the entire server on each log off is beyond me. If you’re talking a server crash and you need to save everything … who you saving this to. The server is not there any more.

The documentation says:

This function binds a function to be called prior to the game shutting down

The condition for “The game shutting down” isn’t very specific, but I assumed that if something happens such as a developer shutting down the server, then it would fire while multiple players are still in the game.

Combined with the code sample on that page which does save data for all players in the game, it seems logical that there can be more than one player on shutdown.

I agree. The page says it’s best to use it, warns of the 30 second limit and hints at the use of paralleling. I take “The game shutting down” as the last player online. Could be wrong …

Thank you very much for the well thought-out reply, I appreciate it.

I would also like to add where you get the link to the new documentation. I usually go through create.roblox.com and click on developer hub, but that takes me to the old one that I understand is technically outdated now (although its search function is much more useful)

Update on this thread: The BindToClose documentation now has an updated code sample exemplifying the method I outlined above.

I go directly to create.roblox.com/docs and use the search feature to find the page I need. My understanding is the “Developer hub” link will redirect to this new site soon, once the old one is fully deprecated.

1 Like