Feature Store Guide
The Feature Store is where you define the features your models use, keep their values fresh, and serve them consistently for both training and live inference. It solves the two problems that quietly break most ML projects: the same feature being computed differently in training than in production (training/serving skew), and training data that accidentally includes information from the future (label leakage).
Open it from MLOps > Feature Store. The list page shows each store with its status, whether online serving is enabled, and the storage it is bound to. Use Create Feature Store in the page header to add one.
Concepts
A feature store is built from four kinds of objects:
- Entity: the thing features describe, identified by one or more join keys. For example, a
driverentity keyed bydriver_id. - Feature view: a named group of features for an entity, with a schema and a data source. A view is immutable per version: an additive change (a new nullable column) reuses the version, while a breaking change creates a new version so existing consumers keep resolving what they were built against.
- Feature service: the model-facing contract. A service pins a specific set of features (at specific view versions) so a model always trains and serves against exactly the same definition.
- Materialization: the scheduled refresh that moves feature values from the offline store into the online store so they can be served with low latency.
Storage
A feature store keeps its definitions in the platform and its feature values in storage you select when you create it:
- Offline store (required): a durable Postgres add-on or Postgres data source. It holds the full history of feature values and is the system of record for point-in-time training data.
- Online store (optional): a Redis add-on or Redis data source. It holds the latest value per entity for low-latency serving. Enable it only when you need real-time features, online serving, or windowed aggregations; a store without it is training-only.
You choose these from your available add-ons and data sources when creating the store, the same way every other feature on the platform selects services. If you do not have a suitable add-on yet, create one first from Add-ons.
Creating a feature store
- Go to MLOps > Feature Store and click Create Feature Store.
- Give it a name (lowercase letters, numbers, and underscores) and an optional description.
- Select the offline Postgres add-on or data source.
- To serve features in real time, turn on online serving and select the Redis add-on or data source.
- Optionally mark the store public so any user in your organization can read it. By default a store is private to you and anyone you share it with.
- Click Create. The store opens to its details page.
Deleting a store, disabling it, or turning off online serving is blocked while a deployed model resolves online features from it. The platform tells you which models are using it so you can unbind them first.
Defining features
You define entities, feature views, and feature services with the Python SDK or the REST API using a single apply call, which registers them in dependency order (entities, then views, then services). Applying the same definition again is safe: an unchanged view is a no-op, an additive change updates in place, and a breaking change creates a new version.
from strongly import Strongly
client = Strongly()
store_id = client.feature_store.list_stores()[0]["_id"]
client.feature_store.apply(
store_id,
entities=[
{"name": "driver", "joinKeys": ["driver_id"], "valueType": "int64"},
],
views=[
{
"name": "driver_stats",
"entities": ["driver"],
"mode": "batch",
"ttl": "2d",
"schema": [
{"name": "conv_rate", "dtype": "float64"},
{"name": "acc_rate", "dtype": "float64"},
],
"source": {
"serviceKind": "addon",
"serviceId": "<your-postgres-addon-id>",
"type": "postgres",
"table": "driver_stats_raw",
"timestampField": "event_timestamp",
"entityKeyColumns": {"driver_id": "driver_id"},
},
},
],
services=[
{
"name": "driver_model_v1",
"features": [
{"view": "driver_stats", "feature": "conv_rate"},
{"view": "driver_stats", "feature": "acc_rate"},
],
},
],
)
Feature views and services appear on the store details page under their tabs, each showing versions, feature counts, and freshness.
Ingesting and refreshing values
Write feature rows into a view's history, then materialize the view to publish the latest values to the online store:
client.feature_store.write(store_id, "driver_stats", rows=[
{"driver_id": 1001, "event_timestamp": "2026-07-30T00:00:00Z", "conv_rate": 0.75, "acc_rate": 0.9},
])
client.feature_store.materialize(store_id, "driver_stats")
Materialization is incremental: it publishes only what changed since the last run and never moves an older value over a newer one. For streaming views, values update continuously as events arrive, and windowed aggregations (for example a 24-hour sum) are kept current automatically.
Serving features online
Once a view is materialized, resolve the latest features for a set of entities. You send only the entity keys and receive the current feature values:
online = client.feature_store.get_online_features(
store_id, "driver_model_v1", entity_rows=[{"driver_id": 1001}]
)
print(online["results"])
Each result reports the resolved features and lists any that were missing (an entity with no value yet), so absent data is always visible and never silently filled in. You can set a maximum staleness so a value older than your tolerance is reported as missing rather than served stale.
Generating training data
To train, ask for point-in-time correct features for a set of labeled examples. For each row, the feature store resolves each feature as of that row's event_timestamp, so a training set never contains information that was not yet known at that moment:
training = client.feature_store.get_historical_features(
store_id,
"driver_model_v1",
entity_rows=[
{"driver_id": 1001, "event_timestamp": "2026-07-30T12:00:00Z", "label": 1},
{"driver_id": 1002, "event_timestamp": "2026-07-30T12:00:00Z", "label": 0},
],
)
print(training["snapshot_url"], training["num_rows"])
The training set is delivered as a Parquet snapshot you read directly. For large label sets, point at a Parquet or CSV file in your storage instead of listing the rows inline:
training = client.feature_store.get_historical_features(
store_id, "driver_model_v1",
entity_s3_uri="s3://your-bucket/labels/train.parquet",
)
Training a model from a feature service
AutoML can train directly on a feature service, so you never assemble the feature matrix by hand:
- Go to MLOps > AutoML and click Train New Model.
- For the dataset source, choose Feature Service.
- Select the feature store and the feature service to train against.
- Upload the entity and label file: a CSV or Parquet frame of entity join keys, an
event_timestampper row, and your target column. - Choose the target column and continue through the wizard as usual.
AutoML resolves point-in-time features for your labels, joins them to the target, and trains on the result. The features it trained on are recorded with the model.
Serving a model with live features
A deployed model can resolve its features automatically at inference, so callers send only entity ids:
- Open the model in MLOps > Model Registry and go to the Features tab.
- Select the feature store and the feature service the model was trained on.
- Turn on online resolution and, optionally, a maximum staleness.
- Click Save binding.
From then on, each prediction request that carries the entity keys is enriched with the service's latest online features before the model runs. Online resolution requires the store to have online serving enabled; the page prevents you from turning it on otherwise. Remove the binding at any time from the same tab.
If feature resolution cannot complete for a request (for example the store is unreachable), the prediction fails clearly rather than serving the model without the features it expects.
Access and sharing
Feature stores are owned by the user who creates them and follow the same sharing model as apps and other library items: keep a store private, share it with specific users, or make it readable across your organization. Every read and write is authorized against your access to the store, so discovering a store never implies permission to use it.