Usually, you keep all the state in memory and save at specific points/actions to a database. Then, not all state is shared with all thousand players, but only within a visible range. And then, not every kind of state is shared with other players. In the end it’s manageable with simple TCP or custom UDP connections.