Skip to content

How MPM worksΒΆ

This page explains what MPM stores, how it turns that into charts, and the concepts the rest of the MPM guides assume. It does not require any knowledge of SQL or of the underlying database.

What MPM is forΒΆ

A model in production makes predictions, and two things can go wrong without announcing themselves:

  1. The world changes. The applicants arriving today do not look like the ones the model was trained on. The model still returns confident answers; they are just increasingly wrong.
  2. The model gets worse at its job. It was 92% accurate at launch and it is 71% accurate now, and nobody notices until someone runs a report.

MPM notices both. It stores every prediction your model makes, and lets you chart it, alert on it, and investigate it over time.

What MPM storesΒΆ

Each time your model makes a prediction, your application sends MPM an event with three kinds of content:

KindMeaningExample
Input featuresWhat the model was shownamount = 240.50, country = "UK"
PredictionsWhat the model saidscore = 0.87, class = "fraud"
Labels (ground truth)What actually turned out to be trueresponse = 1

The third is special: it usually arrives later. You learn whether a transaction was really fraudulent days after predicting it, so labels are attached to an existing prediction afterwards, matched by prediction ID. See Ground truth.

Each model's events are stored in their own table, with a prefix on each column showing what it is:

   __time     timestamp   feature_amount  feature_country  prediction_score  label_response
   ─────────  ──────────  ──────────────  ───────────────  ────────────────  ──────────────
   08-01 09h  175…000     240.50          UK               0.87              1
   08-01 10h  175…600      18.00          IE               0.02              0
   08-01 11h  175…200     990.00          UK               0.94              (not yet)

Those prefixes are how MPM knows what each column is, and which charts it can appear in:

PrefixMeaning
feature_An input to the model
prediction_An output of the model
label_Ground truth

You use the full column name, prefix included, whenever you refer to a column β€” for example in a custom metric formula.

Two kinds of questionΒΆ

MPM answers two quite different questions, through different machinery.

"What is this number, over time?"ΒΆ

You write a formula and MPM charts it per hour or per day:

SELECT ACCURACY("label_response", "prediction_class") FROM MODEL

This is a custom metric, written in a small SQL-like language. MODEL is a keyword standing in for your model's table β€” you never name the table. See Custom metrics.

"Has the shape of this data changed?"ΒΆ

Drift asks something subtler: not "what is the average?" but "is this column's whole distribution different from what it used to be?"

Picture last month's transaction amounts and this month's as two histograms. Drift is a single number summarising how different those two pictures are:

   Reference (training, or the previous period)     Current period

        β–β–ƒβ–…β–ˆβ–…β–ƒβ–                                             β–β–ƒβ–…β–ˆβ–…β–ƒβ–
   ──────────────────────                          ──────────────────────
        ^ centred low                                       ^ shifted right

                        drift score: 0.34  β†’  "quite different"

You do not write a formula for drift. You choose a column and an algorithm. See Drift.

For a model that outputs a probability rather than a class, how well that probability ranks the outcome is a separate question β€” see Classification performance.

How a custom metric becomes a chartΒΆ

   you type a formula
           β”‚
           β–Ό
   the editor checks it as you type        ← errors are underlined immediately
           β”‚
           β–Ό
   saved  (the formula text is stored, not a query)
           β”‚
           β–Ό
   translated into a database query        ← time buckets, filters and names added
           β”‚
           β–Ό
   the database runs it
           β”‚
           β–Ό
   results become one line per metric per filter
           β”‚
           β–Ό
   chart

Two steps are worth understanding, because they explain most of MPM's behaviour.

Everything is grouped into time buckets. A custom metric is always "this value, per hour" or "per day". You never write the grouping; MPM adds it. This is why a metric formula has to reduce to a single number β€” that number is what gets plotted for each bucket.

Filters become extra columns, not extra queries. The filters you set on a dashboard (its predicates) are applied to each metric separately, so one metric with three filters produces three lines on the chart from a single query.

Metrics that look backwardsΒΆ

Some questions cannot be answered one bucket at a time:

  • "How many predictions in total so far this month?" β€” a running total.
  • "What is the 7-day rolling average volume?" β€” a sliding window.

Both need values from other buckets. MPM supports these through window functions:

SELECT SUM("feature_amount") OVER (ORDER BY timeBucket) FROM MODEL
   buckets:    Aug 1   Aug 2   Aug 3   Aug 4   Aug 5
   daily:        10      20      30      40      50
   running:      10      30      60     100     150     ← the running total

Because a running total has to be built from the per-bucket values, only measures whose parts add up to the whole can carry a window β€” sums, counts, minimums and maximums. A running total of per-bucket averages is not an average of anything, so averages and rates are not accepted. See Window functions.

AlertingΒΆ

Anything you can chart, you can monitor. A monitor watches a metric and fires when it crosses a threshold you set, using a comparison you choose β€” greater than, less than, or either of those with equality. Drift is monitored the same way as any other metric, with the threshold set per alert.

Putting it togetherΒΆ

   your application
        β”‚  prediction made                    ground truth arrives later
        β”‚                                              β”‚
        β–Ό                                              β–Ό
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚  event storage:  feature_*   prediction_*   label_*      β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚                                              β”‚
        β”‚ custom metrics                               β”‚ drift
        β”‚ (a formula you wrote)                        β”‚ (a column + algorithm you picked)
        β–Ό                                              β–Ό
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚                    charts and alerts                     β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

GlossaryΒΆ

TermMeaning
EventOne prediction and everything known about it
Ground truth / labelWhat actually happened, usually learned later
FeatureAn input to the model
Time bucketThe hour or day a metric is grouped into
PredicateA dashboard filter, producing its own line on a chart
Custom metricA formula you write, charted over time
DriftA single number for how much a column's distribution changed
Window functionA calculation over other buckets, such as a running total

Where to nextΒΆ

PageWhat it covers
Custom metricsWriting formulas, the full function reference
Window functionsRunning totals and rolling windows
DriftThe four drift algorithms and how to choose between them
Ground truthLate labels, and monitoring the target column
Classification performanceROC AUC, KS, Gini and the gains table
Oct. 19, 2026