24 September 2026 · 5 min read

A pipeline you cannot replay is a spreadsheet

The real product of a CRM is the history of state changes. If it cannot show the pipeline exactly as it stood at nine last Monday, every historical report is a reconstruction.

Ask a CRM a simple question: what did the pipeline look like at nine o'clock last Monday. Not what it looks like now with a date filter, which is a different question with a different answer. What was in each stage, at that moment, before the week's moves. Most systems cannot answer, and the ones that cannot are, whatever their price, a spreadsheet with a login screen. The current state is stored; the history that produced it is not, or is kept for a while and then thrown away. When I designed the pipeline model for the CRM at CustomGlide, this was the question I built around, and the design that answers it is older than any CRM.

The Monday replay test

The test is one query. Pick any past instant and ask the system for the pipeline as it was. A system that passes has a transition log as its source of truth: every change of stage, owner, amount or status is a row with a timestamp, and the current state of a deal is derived from its rows. A system that fails has a mutable deal record whose stage column was overwritten, with maybe a history table on the side that was never the source of anything.

A mutable deal row against a transition log On the left, a single deal row whose stage column has been overwritten: it reads Negotiation and nothing else is known. On the right, a transition log for the same deal with five rows, each with a timestamp, from Lead through Qualified, Demo done, Proposal sent and Negotiation. A query that filters the log to rows at or before a chosen instant and takes the latest reconstructs the state at that instant. One remembers; the other only knows The same deal, stored two ways deals id 4471 stage Negotiation what was it last Monday: unknown stage_transitions 4471 Lead 08-21 10:12 4471 Qualified 08-28 15:40 4471 Demo done 09-04 11:05 4471 Proposal sent 09-12 14:02 4471 Negotiation 09-16 09:30 as of Monday 09-15 09:00: the latest row at or before it, so Proposal sent The left is the state. The right is the state and every state it has ever been, with the current row derived, not stored.
Illustrative: the two storage shapes; the dates are made up for the drawing.

The replay query is short, and it is the same query for every report that asks about the past.

SELECT DISTINCT ON (deal_id) deal_id, to_stage AS stage
FROM stage_transitions
WHERE moved_at <= '2026-09-15 09:00+05:30'
ORDER BY deal_id, moved_at DESC;

Group that by stage and you have the pipeline as it stood. Run it for the previous Monday too and you have the week's net movement, exactly, rather than as a reconstruction from whatever the current rows happen to say about their created and modified dates.

Why the current row is not enough

The reason this matters is not archival tidiness. It is that most of the questions a sales team asks are questions about change, and change is not visible in a snapshot. How much of this quarter's forecast was already in the pipeline at the start of the quarter. Which deals moved backwards last month. How long do deals spend in Negotiation before they close, and has that got longer. Whether the manager's Monday view was right, now that the month has closed. Every one of those is a query over transitions, and every one is a guess if the transitions were not kept.

The disputes are worse than the reports. A rep says the deal was in Proposal Sent when the target was set; the manager remembers otherwise; the system shows Negotiation and a modified-date. Without the log, the argument is settled by seniority. With the log, it is settled by a row.

What the vendors keep

The major CRMs do keep history, and how much they keep is instructive, because each of them treats it as a feature with a limit rather than as the source of truth. Salesforce's standard field history tracking retains changes for up to 18 months in the interface and 24 through the API, and the paid Field Audit Trail add-on extends that to as long as ten years. HubSpot's property history is capped by revisions rather than time, at 45 for contact properties and 20 for deal, company and ticket properties, and deleting a property deletes its history. Zoho CRM's audit log is kept for three years and then permanently deleted.

How long three CRMs keep a field's history Horizontal bars in months: Salesforce standard field history 18, Zoho audit log 36, Salesforce Field Audit Trail up to 120. HubSpot is shown as a note because its limit is 20 revisions per deal property rather than a time. History as a feature with a limit Months of retained history, by product and plan Salesforce, standard 18 Zoho, audit log 36 Salesforce, Field Audit Trail 120 HubSpot keeps the last 20 revisions of a deal property, however long they span, and 45 of a contact property; a deleted property takes its history with it. an add-on, a cap, and a three-year clock: none of them is the source of truth
Source: Salesforce field history retention, Field Audit Trail, HubSpot property history and Zoho CRM audit log documentation, September 2026.

None of that is a criticism of the products. Keeping history as a bounded side table is a reasonable engineering choice for a system whose current state is the product. It is a statement about what the product is. A CRM that stores the state and remembers some of the history is a system of record for the present. A CRM that stores the history and derives the state is a system of record for the business, and the difference shows up the first time someone asks about last Monday.

What "as of" makes possible

Once the log is the source of truth, a class of reports that were previously impossible become ordinary, and they are the reports a sales leader actually wants. Pipeline coverage at the start of a period against bookings at its end, which is the only honest way to judge a forecast. Stage duration distributions computed from the actual entry and exit times of every deal, rather than from a "days in stage" field that resets when someone edits the record. Backflow, the share of departures from a stage that go backwards, which is the subject of another post and is a single query over the same table. A cohort view that follows the deals created in one month through every stage they visited afterwards.

None of these needs a data warehouse or an export. They need the table that a mutable design threw away, kept, and a timestamp parameter on the query. The reporting layer of the CRM shrank when the log arrived, because most of what it had been doing was reconstructing history from clues.

The append-only ledger, without the vocabulary

The pattern has a name in software architecture and a body of writing behind it, and I have avoided the name on purpose, because the name makes it sound like a rewrite. It is not. It is one table, appended to on every change, and one derived view of the latest row per deal. The rest of the application reads the view exactly as it read the old mutable row. The dashboards, the forecasts, the stage reports all become queries over the log with a timestamp parameter that defaults to now.

The cost that people expect, storage, is small. A deal that passes through six stages produces six rows. A pipeline of a hundred thousand deals with a dozen transitions each is a million or so rows of a few columns, which is a small table by any modern database's standard. The growth is linear in activity, and activity is the thing the business wants more of.

Rows in the transition table against deals in the pipeline Three lines over deal counts from ten thousand to one million, on log axes, for an average of six, twelve and twenty-four transitions per deal. At a million deals with twelve transitions each the table holds twelve million rows. The growth is linear and the scale is modest for a relational database. The storage cost is linear and small Transition rows, log scale; a model with stated assumptions 12 per deal 24 6 100M 10M 1M 100k 10k 100k 1M Deals in the pipeline, log scale 12M
Illustrative: rows equal deals times transitions per deal, plotted for three assumed averages; a row here is a handful of columns, so twelve million of them is a modest table.

What it changed

Three things, in the CRM. Every dashboard gained an "as of" parameter, which by default is now and can be any instant, and the forecast page compares the pipeline as it was at the start of the quarter with the pipeline now, from the same query with two timestamps. The stage report that used to be a nightly job that nobody trusted became a view that is correct at any moment because it is computed from the log at that moment. And the argument about last Monday stopped happening, because the system could answer it.

The test is worth running against any system that calls itself a system of record. Pick a Monday. Ask for nine o'clock. If the answer is a reconstruction, a best guess from modified dates and a side table with a retention limit, the system knows the present and has opinions about the past. If the answer is a query, it remembers. A pipeline you cannot replay was never a pipeline. It was a spreadsheet with a stage column, and the stage column has been overwritten.

Data ModellingCRMDatabases
All writing

Written by Mohd Shayan

Get new posts by email

Occasional essays on engineering, AI, and building for the people technology leaves behind.

One email per new post. Unsubscribe any time.

Subscribe with RSS