Realtime deltas, per tile
One broadcast channel per geohash — a client only receives its viewport.

The naive way to build a realtime geo feed is a firehose: every client gets every update. The honest way, for a globe with thousands of tiles and many clients, is one broadcast channel per geohash tile — a client only receives the deltas for its viewport.
The naive way to build a realtime geo feed is a firehose: every client gets every update. The honest way, for a globe with thousands of tiles and many clients, is one broadcast channel per geohash tile — a client only receives the deltas for its viewport.
One channel per tile
The realtime endpoint — GET /api/v1/atlas/ws — does not broadcast every GeoSignal delta to every client. The globe is tiled by geohash prefix, and there is one tokio broadcast channel per tile. A client connects, declares its viewport as a set of geohash tiles, and is subscribed to exactly those channels. When a GeoSignal delta lands in a tile, it goes out on that tile channel, and only the clients watching that tile receive it. A client watching the South Atlantic does not receive a quake in the Pacific.

Why per-tile, not per-client
The alternative is per-client filtering: one global channel, and each client filters on the server side. That works until you have a thousand clients and a thousand filters running on every delta. Per-tile channels move the filtering into the subscription structure itself: the broadcast channel is the filter. A delta published to tile X reaches only the subscribers of tile X, with no per-client check at publish time. The cost of sending is paid once per tile, not once per client per delta. That is the property that makes the realtime layer scale with the number of tiles, not with the number of clients times the number of deltas.
The broadcast channel is the filter. A client watching the South Atlantic does not receive a quake in the Pacific — not because it filtered it out, because it never subscribed to that channel.
The viewport contract
A client declares its viewport as a set of tiles and receives deltas for those tiles. When the viewport moves — pan, zoom — the client sends a new viewport, and its subscriptions update. The connection is user-JWT authed (not Eye-Key), with per-user connection caps so one user cannot open a thousand sockets. Auth and limiting live in the WS handshake and middleware, not in the publish path. The publish path is dumb and fast: delta in, delta out on the matching tile channels.
- One broadcast channel per geohash tile — the structure is the filter.
- Clients subscribe to their viewport tiles; pan and zoom update subscriptions.
- Per-user connection caps and user-JWT auth — the publish path stays dumb and fast.
What this costs
The cost is channel management. There is one channel per tile that has at least one subscriber; tiles with no subscribers have no channel, which keeps the total bounded by the union of all client viewports, not by the total tile count of the globe. A tile with a thousand subscribers broadcasts once, and tokio fan-outs to the thousand. The broadcast primitive is built for this — a fixed-size ring buffer, with slow consumers lagging or dropping, not blocking the publisher. Backpressure is per-consumer, not per-tile.
Scale with the number of tiles that someone is watching, not with the number of clients times the number of deltas. The broadcast channel is the unit that makes that true.
— GeoHub design note
What it is not
Per-tile delivery is not a guarantee of completeness. A slow client can lag the broadcast ring and miss a delta; a disconnected client misses everything while it is down. The realtime layer is a best-effort view of the cache, not a durable queue. The durable record is the Postgres cache; the WS is the live delta on top of it. A client that needs the full state reconnects and reads the snapshot endpoint, then subscribes. We are pre-revenue and building the POC; the per-tile WS is built, and its honesty is that it is a live view, not a durable log.