Visits, not sessions. One row per visit, stitched on write with a 30-minute inactivity timeout.
Two logical databases. Hot, append-only tables use TIDEMARK_ANALYTICS_DB. Everything else uses the default connection. Tables are keyed by site_id and indexed on time.
Stateless app tier. Sessions and cache can move to Redis or the database, and any number of PHP workers can serve requests.
Swappable seams.EventSink (writes) and Stats\Stats (reads) are the only places that know about the storage engine. A columnar implementation can replace them without touching controllers or the UI.
No build step. The dashboard is Preact loaded as plain modules.