Billing, CRM, product and analytics
SCD at the source and an accumulator for what gets deleted
The state of any entity on any day
MRR, commissions, health score and AI agent
What it solves
- MRR, books and status for past months stop changing with today's state.
- Usage and events that the source deletes are kept.
- A sync that fails does not take the history with it.
Business questions it answers
Ask your agent these questions once the case is live.
What you need
- Billing, CRM and product connected to Nekt
- SCD Type 2 turned on for tables that change in place
- The list of business fields worth tracking
What you get
- Versioned tables with validity start and end
- Daily snapshots of usage and calculated metrics
- A coverage map with the start date of each history
- An AI agent that answers how things looked on a date
Where to activate
MRR, active customers and movements for any month, read from that month's state.
Owner of the month and books by cutoff day, for NDR and variable pay without disputes.
Answers how an account looked on a date, stating where the data comes from and since when history exists.
Turning on SCD is one setting per table. Accumulators for sources that delete data need a notebook. The biggest cost is starting late. The detailed view has the business rules, the pitfalls and the acceptance test. Or send everything straight to your agent with the Nekt MCP.
Billing, CRM and product keep only the current state. The subscription that was past_due yesterday shows as active today, the owner of the deal that closed is now someone else, analytics' 30-day usage is overwritten on every sync, and Stripe events and TTL collections disappear after a few weeks. Without stored history there is no MRR for past months, no commission by owner of the month and no usage trend. And a full sync that fails halfway can wipe out months.
How it is usually done, and the rule
Each row is a mistake that already happened in practice.
Enable Nekt's SCD Type 2 on tables that change in place: billing subscriptions and items, CRM customers, deals and companies, product accounts and plans. Every change becomes a version with _available_from, _available_until and _deleted. What came before does not come back: for MRR, rebuild from invoices; for owner and stage, from the CRM property history.
Stripe events are available for about 30 to 40 days, MongoDB collections with a TTL delete documents (about 45 days in a real case) and Amplitude charts and metric spreadsheets return only an overwritten 30-day window. Accumulate into your own table by day and id, with merge, reprocessing the last few days on each run so a failure heals itself.
A SQL transformation on Nekt overwrites the whole table on every run. To snapshot daily MRR, books or aggregated usage, use a notebook with mode merge, or a query that reads its own output and keeps all previous days, replacing only the current day.
Before writing, the routine refuses an empty result or one much smaller than the previous one, unless explicitly allowed. Before a full sync of a large source, take a frozen copy: a full sync that failed halfway once wiped almost five months of events from a table.
In billing, most new versions only advance the billing cycle or swap the latest invoice. To count a change in status, plan, quantity, price or end-of-cycle cancellation notice (cancel_at_period_end), compare the business field with the previous version and count only when it changed.
The state on day D is the version valid at D+1 00:00 Brasília time, that is, D+1 03:00 UTC. With several versions on the same day, the last one wins. Run the session in UTC and convert only at the cutoff, once.
For books, NDR and commissions, the owner in a past month is the owner valid on an agreed day (for example, the 5th, giving the team days 1 to 4 to transfer accounts). Changes after the cutoff are flagged as mid-month transfers, without changing the base owner. The current month uses the latest owner.
When SCD was not turned on in time, recover stage, amount and owner from HubSpot's property history (propertiesWithHistory, one entry per change with value, date and source). If the connector does not bring the property you need, a temporary script fetches it from the API, flagged as temporary and with a removal date.
A past rebuilt from invoices, logs or a backfill is flagged with its origin. Models and indicators use only what was available at the end of the previous period (point-in-time). In a real case, contract attributes rebuilt by a backfill contaminated a churn model and had to be removed.
A closed month is read from the frozen snapshot. A historical reclassification is done once, documented with date and reason, and is not repeated on every run. A later correction goes in as an adjustment in the month it was found.
What to keep and how
Each kind of SaaS data has its own way of not losing the past.
Definitions
Pitfalls that already happened
A full sync of product events failed halfway and wiped almost five months from the table.
Frozen copy before any full sync of a large source.
One run overwrote the daily snapshot table and three weeks had to be rebuilt by hand.
Self-referencing query that only replaces the current day, plus a guard against empty results.
The product's conversations collection deleted documents older than 45 days, and the trend component could never be calculated.
Daily accumulator per customer from day one.
The metrics spreadsheet only held the last 30 days, overwritten daily; there was no way to tell whether 45% adoption was rising from 20% or falling from 80%.
Accumulated weekly or daily snapshot per account.
The connector did not bring deal owner history, and monthly books ended up with today's owner.
Temporary API script, flagged for removal once the connector brings the field.
Contract attributes filled by a backfill leaked later information into the training of a churn model.
Features only from what existed at the end of the previous period.
Acceptance test
The case is done when every item passes.
- For 20 subscriptions, the status on date D read from history matches the invoice or the billing report for that day.
- Every entity has exactly one current version at any instant, with no overlapping validity.
- The daily snapshot has one row per entity and day since the first collection, and gaps are listed.
- Running the routine twice on the same day does not change earlier days' snapshots.
- A run with an empty result fails without writing.
Agent package
Paste into Claude, ChatGPT or any client with the Nekt MCP connected.
State history - For any question about the past, use the versioned table or the daily snapshot, never the current-state table. - State on date D = version with _available_from up to D+1 03:00 UTC and _available_until null or later. Current today = _available_until null and _deleted false. - A new version is not a business change. Change = status, plan, quantity, price, cancel_at_period_end, owner or stage different from the previous version. - Owner of the month = owner valid on day <cutoff day> of the month; in the current month, the latest owner. - Coverage: <table> has history since <date>. Before that, data is rebuilt and flagged; say so in the answer. - A day with no snapshot is a gap, not zero. - A closed month comes from the frozen snapshot; do not recalculate. Client exceptions: - <client>: deal owner history comes from a temporary script until <date>. - <client>: one-off reclassification done on <date> for reason <reason>; do not reapply.
Build the "State history" case in my Nekt workspace following the rules at https://academy.nekt.com/en/industrias/saas/historico-de-estado.md. 1) Find the source tables and confirm the columns the rules use. 2) Create a transformation at the stated grain applying every rule. 3) Run the acceptance test and show me the result of each item. 4) Create the case's context document in the workspace, leaving my clients' exceptions open for me to fill in.
Variations
Customer freezes and deactivations rebuilt as periods (start and end) from automation events, with no overlap.
Lead score and health score stored daily, to measure whether the rule was right without rewriting what the team saw.
Attributes per account and month calculated at the end of the previous month, to predict churn and NRR without leaking the future.