engineering by snakken
Security 2026-03-05 · 2 min read

Your exact location never leaves your device

Snakken is a location app whose servers never see a location. How we use H3 cells computed on the phone to know your neighbourhood without ever learning your coordinates — and why we designed the API so we couldn't cheat later.

Snakken's entire product is "what is happening right around you". The obvious way to build that is the way almost everyone builds it: the app sends your GPS coordinates to the server, the server figures out what is nearby, done. We decided early that this was the one architecture we would not build — because a server that knows where every user is standing is a liability you cannot patch away later.

The constraint we set ourselves

The rule is simple to state: coordinates are device-only data. Nothing that leaves the phone may contain latitude or longitude, at any precision, in any field, ever. The server is allowed to know one thing about your position: which neighbourhood cell you are in.

H3, computed on the phone

We use H3, Uber's open-source hexagonal grid system, to turn the world into discrete cells. The important part is where the conversion happens: the phone resolves its own GPS fix into a cell index locally, throws the fix away, and sends only the cell.

A cell index like 881f1d4887fffff says "somewhere in this hexagon" — at the resolution we use, an area on the order of a neighbourhood, deliberately big enough that it describes a community rather than a person. It is the digital equivalent of telling someone you live in Kreuzberg, not handing them your door key.

The grid is also why this stays honest under load: cells are stable identifiers, so "give me the feed for my cell" is a cacheable, indexable query that never needs a coordinate to answer.

Designing so we can't cheat

A policy that says "we don't store coordinates" is worth little; policies change. We wanted the stronger property: the API cannot express a coordinate.

  • There is no request or response field anywhere in the API schema typed as latitude, longitude, or geo-point. The schema simply has no vocabulary for it.
  • The cell resolution is fixed in the protocol. A client cannot send a "more precise" cell than the neighbourhood resolution, because finer indices are rejected at the boundary.
  • Distance hints in the feed ("120 m") are computed on the device, from the device's own position against place locations that are public data — the café's address, not yours.

The practical effect: if someone compromised our database tomorrow, the most precise location fact they could learn about you is the same thing your neighbours already know — that you are one of the people in this neighbourhood.

What this costs us

Honesty requires the trade-off list. Cell-only location means we cannot rank the feed by exact distance (we sort within a cell by time instead — which conveniently is also the product philosophy). Cell boundaries are arbitrary lines; if you live on one, your "neighbourhood" may be the hexagon next to the one you'd draw yourself. And debugging location issues is harder when, by design, no log anywhere can tell us where a user actually was.

We consider all three a fair price. The fourth cost — explaining to every new engineer why there is no lat field — this article is meant to pay down.

// Published under CC BY 4.0 — take the patterns, cite the source. · ← All articles