One table that every analytics surface in the platform reads. Each row carries the event type, the real event time (separate from the insert time so backfills stay honest), the previous stage's entry instant, the seconds spent there computed at write time, the deal-owner snapshot, the actor and their role at the time, and the human stage label as it read that day.
Also called: stage transition log · lead history · audit trail of every stage move · event spine
- 1A stage move writes one row: from-stage, to-stage, the label of the to-stage as it read at that moment, and duration_seconds for the stage just left.
- 2duration_seconds is computed at write rather than by a later window function, so one missing row can't corrupt the whole chain.
- 3Owner, actor, actor role, contact id and contact name are denormalised onto the row.
- 4Indexes cover org+owner+time, org+time and org+event type so range scans and per-person rollups stay fast.
Migration 096: 'We EXTEND the existing append-only stage_transition_log (migration 088) into a durable, self-describing lifecycle-event spine instead of creating a parallel table — keeping a single source of truth.' The duration snapshot exists 'so a single missing row can't corrupt the chain', and the denormalised owner/label/contact exist so a row 'stays meaningful even if the opportunity is later edited, re-linked, or deleted.' Migration 088 is equally blunt about the boundary: the log is 'audit, never a state store.'
- Renaming a pipeline stage used to rewrite history in every past report.
- Reassigning a deal moved credit for work already done.
- No record existed of who actually moved a deal versus who owned it.
See it on your own jobs
Twenty minutes, your numbers, no slide deck. We’ll build one of your real buildings in front of you and send you the estimate link at the end — yours to keep either way.
or keep browsing features →