GeoSignal ids are deterministic
uuidv5(source, native_id) — re-ingest updates, never duplicates.

Re-ingesting a feed should update, not duplicate. That sounds obvious until you run it and your cache fills with ten copies of the same quake. The fix is deterministic ids: every GeoSignal is identified by uuidv5(source, native_id), so the same event from the same feed always maps to the same row.
Re-ingesting a feed should update, not duplicate. That sounds obvious until you run it and your cache fills with ten copies of the same quake. The fix is deterministic ids: every GeoSignal is identified by uuidv5(source, native_id), so the same event from the same feed always maps to the same row.
Deterministic, by construction
A GeoSignal carries an id. That id is not a random uuid or a database sequence; it is uuidv5 of two things: the source key (which feed) and the native_id (the identifier the feed itself assigns). The same event, ingested twice, produces the same id twice. The upsert into the Postgres cache is therefore an update when the event already exists and an insert when it does not — never a duplicate. The id is a function of the inputs, not a minted value, which means re-ingest is safe by construction.

Why uuidv5 and not a hash
A hash would also be deterministic. uuidv5 is a hash — SHA-1 over a namespace (the source key) and a name (the native_id) — packaged as a uuid, which means it fits the uuid column type, sorts and indexes like a uuid, and is recognizable as an id to every tool that speaks Postgres. The choice is pragmatic: deterministic, typed, and boring in the way that infrastructure should be boring. The important property is not the algorithm; it is that the id is a pure function of (source, native_id), computed the same way every time.
The id is a function of the inputs, not a minted value. Re-ingest is safe by construction because the same event always maps to the same row.
What updates, what does not
An upsert updates the mutable fields of a GeoSignal — position, intensity, status — and leaves the id stable. That means a client tracking a signal over time tracks one row that changes, not many rows that appear and disappear. The GeoPublisher hands the delta, and a client on the realtime WS sees the update, not a new event. Deterministic ids are what make the realtime layer coherent: a per-tile broadcast channel is useful because the messages on it are updates to known signals, not a stream of novelty.
- uuidv5(source, native_id) — the id is a pure function of the feed and the native identifier.
- Re-ingest updates; it never duplicates — the upsert is safe by construction.
- Clients track one changing row, not many appearing rows — the realtime layer stays coherent.
The assumption it rests on
Deterministic ids assume the native_id is stable — that the feed calls the same event by the same name across ingests. That is true for most feeds (a quake has a USGS event id; a flight has an ICAO callsign) and false for a few (a feed that mints a new id per poll would defeat this). The SourceDescriptor and the mapper are where that assumption is enforced: the mapper is responsible for extracting a stable native_id, and a feed that does not have one is a feed that needs a different strategy. The id discipline is a contract between the mapper and the cache, and the mapper is where it is upheld.
Re-ingest should update, not duplicate. The only way to guarantee that is to make the id a function of what the feed says the event is — not a function of when you ingested it.
— GeoSignal identity note
What it is not
Deterministic ids do not make the data correct. They make it coherent — one row per event, updatable, trackable. Accuracy is still a property of the source and a question for calibration, which is gated (Gate 1b). We are pre-revenue and building the POC; the id scheme is built, and the coherence it gives is a substrate property, not a truth claim.