The Feature Store Problem
In a mature ML platform, features are computed by many teams for many models. Without a shared infrastructure:
- Duplication: every team recomputes the same features (customer lifetime value, 7-day transaction count)
- Training-serving skew: the feature logic in training notebooks differs subtly from production code
- Leakage: joining features to labels without respecting event timestamps contaminates training data
- Latency: complex aggregations computed at request time blow through latency budgets
A feature store solves all four problems with a centralized layer that serves pre-computed features both for training (offline) and prediction (online).
Core Concepts
Offline vs. Online Serving
| Layer | Storage | Use Case | Latency |
|---|---|---|---|
| Offline store | Data warehouse (BigQuery, Snowflake, Parquet) | Training data retrieval | Seconds–minutes |
| Online store | Key-value store (Redis, DynamoDB, Bigtable) | Real-time prediction serving | Milliseconds |
The offline store holds the full history. The online store holds the latest feature values for each entity (user_id, product_id, etc.) for low-latency inference.
Point-in-Time Correctness — A Concrete Example
Suppose you're training a fraud model. Each training example is a transaction labeled fraud/not-fraud. You want to attach the user's "number of transactions in the past 7 days" feature.
Incorrect join (leakage):
transaction_date | user_7day_count (computed today)
2024-01-10 | 42 ← uses data from after Jan 10!
Point-in-time correct join:
transaction_date | user_7day_count (as of Jan 10)
2024-01-10 | 5 ← only uses data available on Jan 10
A feature store handles this join correctly by design.
Feast
Feast (Feature Store) is the most popular open-source feature store. It is backend-agnostic and supports many offline/online storage combinations.
Key Abstractions
- Entity: the primary key (e.g., user_id, driver_id)
- FeatureView: a set of features computed from a data source, associated with an entity
- FeatureService: a named collection of features served together to a model
- DataSource: where raw data lives (BigQuery table, Parquet file, Kafka stream)
from datetime import timedelta
from feast import Entity, FeatureView, Field, FileSource
from feast.types import Float32, Int64
# Define entities
user = Entity(name="user_id", description="User identifier")
# Define data source (could also be BigQuery, Snowflake, etc.)
transactions_source = FileSource(
path="data/features/user_stats.parquet",
timestamp_field="event_timestamp",
created_timestamp_column="created",
)
# Define feature view
user_stats_fv = FeatureView(
name="user_stats",
entities=[user],
ttl=timedelta(days=1),
schema=[
Field(name="transaction_count_7d", dtype=Int64),
Field(name="avg_amount_7d", dtype=Float32),
Field(name="distinct_merchants_7d", dtype=Int64),
],
online=True,
source=transactions_source,
)from feast import FeatureStore
import pandas as pd
from datetime import datetime
store = FeatureStore(repo_path="feature_repo/")
# Materialize features into the online store (run before serving)
store.materialize_incremental(end_date=datetime.utcnow())
# --- Offline: point-in-time correct training dataset ---
entity_df = pd.DataFrame({
"user_id": [1001, 1002, 1003],
"event_timestamp": [
datetime(2024, 1, 10),
datetime(2024, 1, 11),
datetime(2024, 1, 12),
],
"label": [0, 1, 0],
})
training_df = store.get_historical_features(
entity_df=entity_df,
features=["user_stats:transaction_count_7d", "user_stats:avg_amount_7d"],
).to_df()
# --- Online: real-time feature retrieval for inference ---
online_features = store.get_online_features(
features=["user_stats:transaction_count_7d", "user_stats:avg_amount_7d"],
entity_rows=[{"user_id": 1001}, {"user_id": 1002}],
).to_dict()Tecton
Tecton is the enterprise, fully managed feature platform. It extends the feature store concept with:
- Streaming features: real-time feature computation from Kafka/Kinesis with guaranteed freshness
- On-demand features: computed at request time from request payload (no pre-materialization)
- Feature monitoring: automatic drift detection and freshness alerts
- Git-based feature management: features defined in Python, versioned in Git, deployed via CI/CD
Best for: large organizations that need real-time streaming features and enterprise SLAs. Requires Databricks or Snowflake.
import tecton
from tecton import stream_feature_view, Aggregate
from tecton.types import Float64, Int64
from datetime import timedelta
# Streaming feature: real-time 1-hour transaction count
@stream_feature_view(
source=kafka_transactions, # Kafka/Kinesis stream source
entities=[user],
mode="spark",
aggregation_interval=timedelta(minutes=1),
features=[
Aggregate(input_column="amount", function="count",
time_window=timedelta(hours=1)),
Aggregate(input_column="amount", function="sum",
time_window=timedelta(hours=1)),
],
online=True,
offline=True,
ttl=timedelta(days=7),
)
def user_transaction_metrics(transactions):
return transactions.select("user_id", "amount", "timestamp")Hopsworks
Hopsworks is an open-source, full-stack ML platform with a feature store at its core. It includes:
- Feature Store (HSFS): online/offline feature serving with Spark-based transformations
- MLflow integration: experiment tracking built in
- Model Registry: model versioning with deployment to KServe
- Jupyter notebooks + Jobs: development and scheduled pipeline execution
Best for: teams that want a single self-hosted platform covering feature store, model registry, and serving.
import hopsworks
import pandas as pd
project = hopsworks.login()
fs = project.get_feature_store()
# Create a feature group
user_stats_fg = fs.get_or_create_feature_group(
name="user_transaction_stats",
version=1,
description="7-day aggregated user transaction features",
primary_key=["user_id"],
event_time="event_timestamp",
online_enabled=True,
)
# Insert data (batch or streaming)
user_stats_fg.insert(user_stats_df)
# Create a feature view for training
feature_view = fs.create_feature_view(
name="fraud_features",
version=1,
query=user_stats_fg.select(["transaction_count_7d", "avg_amount_7d"]),
labels=["is_fraud"],
)
# Generate training dataset with point-in-time correctness
X_train, X_test, y_train, y_test = feature_view.train_test_split(test_size=0.2)Comparison
| Criterion | Feast | Tecton | Hopsworks |
|---|---|---|---|
| License | Open source (Apache 2) | Enterprise SaaS | Open source + Enterprise |
| Streaming features | Limited | Native, real-time | Via Spark Streaming |
| Managed service | No (self-hosted) | Yes | Optional |
| Platform scope | Feature store only | Feature store + monitoring | Full ML platform |
| Best for | Open-source, flexible backends | Real-time, enterprise scale | Self-hosted full platform |
Knowledge check
Why is point-in-time correct feature retrieval critical for training data construction?
Summary
- A feature store provides centralized, versioned, reusable features with online/offline serving
- The offline store (data warehouse) serves training data; the online store (key-value) serves real-time predictions
- Point-in-time correct joins prevent training data leakage — features are retrieved as of the label event timestamp
- Feast is the most flexible open-source option; Tecton adds real-time streaming; Hopsworks provides a full ML platform
- Materialization moves computed features from the offline store into the online store for low-latency serving
Next: model serving and inference with FastAPI, TorchServe, Triton, and ONNX.