Real-time and multiplayer basics
Ask again, or listen?
Kai wants a friends board in Hyper Shards where a friend's new score pops up the moment it lands. There are two ways to do it.
Asking again: the game requests the board every 10 seconds. This is called polling. Most answers say "nothing changed", each one still costs a read, and news can be up to 10 seconds late.
Listening: the game keeps a connection open, and the server pushes news the instant something changes.
Listening with onSnapshot
In Firestore (Firebase's database), listening looks like this:
const stop = onSnapshot( doc(db, "leaderboards", "friends"), (snap) => drawBoard(snap.data()));
The function we pass runs once straight away with the current data, then again every time the document changes. A snapshot is a copy of the data at that moment. onSnapshot hands back a function, here called stop. Calling stop() ends the listening.
Real-time has a price
Listening is not free. At the time of writing, Firestore charges one read when a listener starts, and one more read every time a watched document changes.
If 10,000 players keep the board open while it changes 100 times, that's 10,000 x 100 = 1,000,000 reads. So we listen only while the screen is showing, and call stop() the moment it closes. A listener that is never stopped keeps running, and keeps costing, in the background.
Bug hunt
1function openBoardScreen() {2 onSnapshot(doc(db, "leaderboards", "friends"),3 (snap) => drawBoard(snap.data()));4}5function closeBoardScreen() {6 hide("board");7}
Each time a player opens and closes the board, reads go up and never come down. What is missing?
- Keeping the stop function from onSnapshot and calling it in closeBoardScreen
- Polling the board every second instead
- A bigger limit() on the query
Show the answer
Keeping the stop function from onSnapshot and calling it in closeBoardScreen
Each open starts a new listener, and nothing ever ends it. Saving const stop = onSnapshot(...) and calling stop() when the screen closes ends the listening and the extra reads.
Latency and ping
Latency is the time a message takes to travel. Ping is the round trip, there and back, measured in milliseconds (ms). To a server in your own city, ping might be 10 to 30 ms. To the other side of the world, often 200 to 300 ms.
No code can fix distance. Even light in a glass fibre cable needs about 100 ms just to reach the far side of the planet. And at 60 FPS a new frame comes every 16.7 ms, so every message arrives a few frames late.
Read the numbers
In a race, the other player's ship position takes 100 ms to reach Kai's laptop. At 60 FPS (a frame every 16.7 ms), about how many frames old is the ship Kai sees?
- About 1 frame
- About 6 frames
- About 60 frames
Show the answer
About 6 frames
100 divided by 16.7 is about 6. Kai always sees the other ship where it was 6 frames ago, which is why fast online games feel so tricky to build.
Why fast action is hard
In a live shooter, every player sees the others slightly in the past. Two pilots fire at the same moment. Who hit first? Each laptop thinks it did.
Pro games use an authoritative server: one referee that runs the real game. Players send only their inputs ("I pressed fire"), and the server decides what happened and tells everyone. A hacked game can't teleport its ship, because the server never asked it where it was. That needs dedicated game servers running all day, which cost money. Firestore isn't built for it.
Easier first steps
- Turn-basedPlayers take turns, like chess. One small write per move, and a second of lag doesn't matter.
- Ghost racesSave a run (the inputs and the random seed), then let others race a see-through ghost of it later. One write, one read.
- Shared goalsEveryone adds to one big number, like "all players together pop 1 million pests this week".
These are called asynchronous multiplayer: players don't need to be online at the same time.
Pick the mode
Next week: live 4-player Garden Defense battles! Every pest position goes into Firestore 60 times a second.
What is the best reply from the team?
- Start with ghost races or turn-based play. Firestore isn't built for 60 writes a second, and live battles need an authoritative server
- Great, and let's make it 120 times a second for smoothness
- Let's skip the server and let each phone decide who won
Show the answer
Start with ghost races or turn-based play. Firestore isn't built for 60 writes a second, and live battles need an authoritative server
Firestore suits a few writes, not 60 a second per player. Asynchronous modes give players the fun of competing now, and live battles can come later with proper game servers.
Real-time, the smart way
Listen instead of polling, stop listeners when screens close, and start with ghost races before live battles. That's how a small studio adds the thrill of other players without a huge bill.
Next, we look inside live multiplayer: how an authoritative server, prediction and smoothing decide what really happened in a match.
Bolt says: Hyper Shards ghost races could be our first multiplayer mode. Race your friend's best run, any time.
Fact-checked 9 October 2026
- Cloud Firestore: get realtime updates firebase.google.com
- Cloud Firestore billing (listener reads) firebase.google.com
- Cloud Firestore best practices firebase.google.com