Design for the access pattern first, then pick partitioning + the right index/PK so any single query touches a small, bounded slice — never scans 10B rows. Sub-100ms over 10 billion records is not about a faster disk; it's about making the working set tiny.
Query ─▶ Router ──▶ Partition (by tenant/time) ──▶ Index/PK lookup ─▶ ~thousands of rows
│ (prune 99.9% of data) (B-tree / sort key)
└─▶ Cache (Redis) ─▶ hit? return in <5ms
miss ▼
Columnar store (ClickHouse) for aggregates / scans
Access patterns drive everything
Before choosing tech, ask: "Get user X's last 20 orders" is a point/range query — you want the partition and sort key to match it exactly. "Sum revenue by region this month" is an analytical scan — a row store is the wrong tool. Modeling the query first is what separates a design that works from one that looks reasonable but full-scans.
