BI · KPI time series

Historical KPIs in a living spreadsheet

A snapshot of each KPI per period, stored when the period closes and never rewritten, in a spreadsheet that updates itself and keeps the trend the source system forgets.

UsageCommon
EffortMedium
ForCompanies that track KPIs month over month and today rely on screenshots, copied spreadsheets or a system that only shows the current value.
Source

Metric gold tables, short-window sources and manual entries

Rule

Snapshot at close, append-only, validated catalog

Outcome

KPI series per period, with status and batch

Activation

Living spreadsheet, trend dashboard and AI agent

What it solves

  • A closed month's number does not change after it is presented.
  • Sources that only keep the last few weeks stop erasing the past.
  • Automatic and manual KPIs live in a single series, with an owner and a definition.

Business questions it answers

Ask your agent these questions once the case is live.

How have revenue, active customers and churn evolved over the last 12 months?
Is the August number we presented the same one in the spreadsheet today?
Which KPIs have been below target for three months in a row?
How many followers did we have at the end of each month last year?
Who owns each KPI and when was the last entry?

What you need

  • The source metrics in gold tables or connected sources
  • A KPI catalog: name, definition, unit, owner and frequency
  • The destination spreadsheet or the trend dashboard

What you get

  • An append-only KPI values table, with load batch and data status
  • A read view with the last valid value for each KPI and period
  • Frozen closed months, with corrections recorded as adjustments
  • The living spreadsheet with the series, updated after every load

Where to activate

Living spreadsheet

Reverse ETL to Google Sheets in automatic tabs, with the series and the latest value per KPI.

Trend dashboard

A 12 or 24 month series read from the frozen table.

AI agent via MCP

Answers about trends with the number that was presented, not a recomputation.

Ready to build?

The calculation for each KPI usually exists. The work is building the catalog, storing the snapshot at the right moment and starting now: the past the source erased does not come back. The detailed view has the business rules, the pitfalls and the acceptance test. Or send everything straight to your agent with the Nekt MCP.

The problem

The KPI spreadsheet is filled in by hand or recomputed from scratch on every run. When the CRM changes a deal's stage or a classification rule is adjusted, past months change too. When the API only returns the last few weeks, the history disappears. And the transformation that was meant to keep the snapshots recreates the whole table on every run. In the end, nobody trusts the series and every meeting starts by checking numbers.

How it is usually done, and the rule

Each row is a mistake that already happened in practice.

The common wayThe rule
01
Recomputing every month from the current state of the sources.
The snapshot is stored at close, not recomputed

For each KPI and period, store the value when the period closes (previous closed day, closed month) in an append-only table. Recomputing the whole series on every run rewrites the past: in a real case, a qualification rule adjusted mid-month started applying to old sign-ups and a month that had already been presented shrank on its own.

02
A SQL snapshot that overwrites the whole table.
SQL transformations do not keep history

A SQL transformation on Nekt recreates the table on every run and would erase earlier snapshots. To accumulate, use a notebook writing in append or merge mode, or a query that reads its own output table and replaces only the current period. Refuse to write when the result is empty: an empty write wipes the series.

03
Trusting the API to return history when you need it.
Short-window sources need an accumulator

Analytics, product charts, social media and customer service tools often return only a moving window of days or weeks. Accumulate in your own table, one record per day or per id, never deleting, with first and last extraction dates. A rolling window does not repopulate the past: what was not stored is gone. That is why the accumulator starts today.

04
Spreadsheet columns renamed every quarter.
KPI catalog with a stable id

Each KPI has a kpi_id that never changes, a name, definition, unit, value type, owner, area and frequency. An entry for a KPI outside the catalog is rejected. Changing the definition of a KPI that already has history requires an explicit decision and a series review, or a new KPI.

05
Deleting and rewriting the month's value when someone corrects it.
Each load is a batch, and the last valid one wins

Each run writes a batch with an identifier, a sequence number, who filled it in (routine or person) and when. A batch is all or nothing: one invalid row rejects the whole batch. Reading uses, per KPI and period, the value from the batch with the highest sequence. Rerunning the same batch writes nothing new.

06
Leaving the month open forever.
A closed month freezes in two rounds

At close, store a provisional version and allow one correction, which becomes final. Later corrections come in as adjustments, with the reference period recorded, without rewriting the final number. Reopening a frozen month is a manual action, with a reason and an owner.

07
Storing zero when the source did not load.
Data status on every value

Store whether the value is ok, partial or missing. A day with no source load does not become zero: it stays missing, and a gap raises an alert. The current month comes in as partial and is not compared with a closed month.

08
Summing each month's active customers to get the year.
Stock, flow and rates are stored differently

Stock KPIs (active customers, followers, balance, MRR) are the value on the last day of the period. Flow KPIs (sales, leads, cancellations) are the sum over the period. Rates are stored with numerator and denominator so quarter and year can be recomputed. Currency-converted values keep the rate used for the month and freeze with it.

09
The team editing numbers in the same tab the routine overwrites.
The spreadsheet only reads

The series reaches the spreadsheet through reverse ETL, in automatic tabs that only the routine writes. Manual tabs (comments, targets) stay separate and are never overwritten. A manual KPI entry goes through the entries table, validated against the catalog, not typed into the automatic tab.

What each row of the series stores

One row per KPI, period and batch. Reads take the last valid batch.

Stable catalog identifierKPIkpi_id
Closed reference day or monthPerioddata
Value, plus numerator and denominator for ratesValuevalor
ok, partial or missingData statusstatus_dado
Load identifier and sequenceBatchbatch_id, carga_seq
Routine or person, and whenOriginpreenchido_por, preenchido_em
Provisional, final or adjustmentCloseversao

Definitions

KPI value
value of the KPI for a kpi_id and a period, written by a batch; reads use the valid batch with the highest sequence
Stock KPI
value on the last day of the period: active customers, followers, balance, MRR
Flow KPI
sum of events in the period: sales, leads, cancellations
Rate
period numerator / period denominator, stored separately; quarter and year recomputed from the sums
Closed period
previous day in local time or a finished calendar month; the current period is partial
Frozen month
month with a final version stored; it only changes through a recorded adjustment
Series coverage
periods with status ok / periods since the KPI started

Pitfalls that already happened

The month shrank after the meeting

A qualification rule recomputed on every run started applying to old sign-ups, and a month's number dropped after it was presented.

Stamp the verdict on the day of the event and never rewrite it.

One write erased weeks

A run overwrote the snapshot table and about three weeks had to be rebuilt.

Append mode and a guard against empty writes.

The API only returned weeks

The customer service tool only delivered the last few weeks of tickets, and the previous month had less than half of the real tickets in the table.

An accumulator per id from the first load.

Social media with no past

A social network API only covered recent months; years of daily series existed only in a spreadsheet exported earlier.

Load the history once as a frozen source and join it with the new series at a hard date cutoff.

A full reload that erased months

A full event reload failed halfway and erased months from the source table.

Take a frozen copy before any full reload.

A zero that was a missing load

A business day with no records for any account showed up as zero in the series; it was a source load failure.

Missing status, not zero, and a gap alert.

Acceptance test

The case is done when every item passes.

Agent package

Paste into Claude, ChatGPT or any client with the Nekt MCP connected.

Full Markdown
Historical KPIs
- The official series is in <values table>; read it through the view <read view>, which returns the last valid batch per KPI and period.
- Each KPI has a kpi_id, definition, unit, owner and frequency in the catalog <catalog table>. Use the catalog definition.
- Months with a final version do not change. Later corrections appear as adjustments, with the reference month.
- The current month is partial: do not compare it with a closed month.
- Stock KPIs (active customers, followers, balance, MRR) = value on the last day of the period; never sum months.
- Flow KPIs = sum over the period. Rates: recompute quarter and year from numerator and denominator.
- Missing status is not zero: say there is no data for that period.
- Never recompute a closed period from the source tables to answer; use the series.
Client exceptions:
- <client>: KPI <kpi_id> changed definition on <date>; before that the series uses <old rule>.
- <client>: history for <source> before <date> comes from <frozen spreadsheet>.
- <client>: reporting exchange rate = monthly average from <rate source>, frozen at close.

Variations

Manual entry

Leaders enter KPIs that have no automatic source through a routine that validates against the catalog.

Target vs actual

The target comes in as another value for the same kpi_id, with the plan version frozen.

Weekly entity snapshot

For fields the CRM does not version, a weekly snapshot of the deal alongside the KPI series.