ML Systems Lab Open interactive version →
Intermediate 30 min read feature engineeringonline featurespoint-in-timebackfill

Feature Engineering in Production

Online vs offline features, point-in-time joins, backfill risk

A fraud model ships with 94% offline AUC. In production it scores 82%. No code changed. No error fired. The model is even getting the exact feature it trained on — "number of transactions in the last 7 days" — but the *value* is wrong.

At training time that number came from a SQL query over a history table: an exact count. In production it comes from a Redis structure that counts approximately to stay fast. For most users the two agree. For high-volume accounts — the very users most likely to be fraud — the approximation drifts furthest from the true count, since probabilistic counters like HyperLogLog trade precision for speed exactly where volume is highest. The model was taught to trust these counts as exact, and now it is scoring live traffic on values it never learned from. Twelve points of accuracy, gone. Not a model failure — an infrastructure failure.


The same five culprits, in feature terms

*Language:* the Python training code and the Java serving code implement one formula two ways, and the small differences add up. *Data source:* batch SQL and real-time Redis handle nulls and completeness differently. *Timestamp:* training computes the feature at label time, serving computes it at request time hours later — for a rolling 7-day window that gap matters. *Preprocessing:* a scaler saved under one library version can load differently under a newer one, shifting every value silently. *Leakage:* a training feature used data that won't exist at serving time, inflating the offline score.

One shared computation path removes four of the five at once — language, data source, timestamp, and preprocessing all collapse into a single well-tested implementation: a single library or service computes "transactions in last 7 days" identically whether the caller is the training pipeline or the live endpoint. Leakage needs one more discipline on top of that: even a single shared function will leak if it's called with a wrong or late as-of timestamp, so point-in-time join enforcement is required in addition to the shared path, not replaced by it.


Point-in-time joins: the rule that keeps training honest

Here is the subtle one. When you build a training row for a fraud event at time T, you must join only feature values that existed *before* T. Grab a value from T + 1 hour — easy to do by accident, because the training job ran later — and you've leaked the future into the past. For a rolling 7-day window computed an hour late, the count can include transactions that happened *after* the event you're trying to predict. The model learns a pattern built partly on future data. In production it never has the future, so the offline number is a mirage and production comes in lower.


One warning worth internalizing. "It's the same logic, just in another language" is a hope, not a fact — it's only true once you've tested that both produce byte-identical output on identical input. Re-implementing SQL window logic in Java quietly changes null handling, overflow, and rounding, and on high-value accounts those small differences can outweigh the model's entire learned signal for that user.

Key points

Takeaway

Training-serving skew from language, data source, timestamp, and preprocessing differences is not discovered through monitoring — it is prevented by building a single feature computation path that makes two diverging implementations structurally impossible. Skew from leakage needs one more discipline on top: point-in-time join enforcement.

Recap

Check your understanding

Q1. You are building a loan default prediction model with a "total_outstanding_loan_balance" feature. Which two statements about implementing training and serving correctly are true?

Q2. Your team is rebuilding a feature pipeline that has a known bug affecting 5% of users. You need to retrain the model with corrected features. What are the risks?

Q3. Explain why a 30-day rolling average feature is particularly prone to training-serving skew.

Q4. A product team wants to add a real-time "user_session_length_so_far" feature to a fraud detection model. Latency SLA is 20ms. How do you evaluate and implement this?

Try it interactively

ML Systems Lab is a free interview-prep platform for ML engineers — work through the full interactive module, quizzes, and drills.

Open ML Systems Lab →