Real-time and multiplayer basics

Play this lesson

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

friends-board.js
function openBoardScreen() {  onSnapshot(doc(db, "leaderboards", "friends"),    (snap) => drawBoard(snap.data()));}function closeBoardScreen() {  hide("board");}

Each time a player opens and closes the board, reads go up and never come down. What is missing?

  1. Keeping the stop function from onSnapshot and calling it in closeBoardScreen
  2. Polling the board every second instead
  3. 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?

  1. About 1 frame
  2. About 6 frames
  3. 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

These are called asynchronous multiplayer: players don't need to be online at the same time.

Pick the mode

#studio-chat, Remy
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?

  1. Start with ghost races or turn-based play. Firestore isn't built for 60 writes a second, and live battles need an authoritative server
  2. Great, and let's make it 120 times a second for smoothness
  3. 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