Engineering Decisions
The decision nobody enjoys
- Append-heavy. The design target was 10 million events per fifteen minutes.
- Deletes are frequent and large. A user deletes a run. A tenant is deleted and the cascade removes everything they ever sent. Both remove a contiguous slice of history, not scattered rows.
- Reads are time-range analytics. Flake rates over a window, failure clusters in the last fortnight, trend buckets.
- Writes are not append-only. This is the one that matters, and it is the one that is easy to miss.
Why not ClickHouse
What we chose, and what it cost
Hypertables forbid cross-hypertable foreign keys, so hierarchy integrity moves out of the database and into the application layer, and the partition column has to be carried in every primary key.That is a permanent tax. Every table in the event path carries run_start_time in its primary key whether it wants to or not, and the guarantees a foreign key would have given us for free are now our job to enforce in code. Writing it down was not ceremony. It meant that six months later, when somebody hit the missing foreign key and asked why, the answer was a paragraph in a decision record rather than an afternoon of archaeology and a suspicion that the original author had not thought about it.