---
title: "Real-time features for ML | Snowplow Signals"
description: "Serve the features you trained on. One definition builds a point-in-time correct training set and serves the live value at inference."
source: https://signals.snowplow.io/use-cases/model-features
---

[Solutions](https://signals.snowplow.io/solutions) / Use case 

# Serve the features you trained on. 

A model trained on the notebook's version of a feature and served a production rewrite drifts without anyone noticing. Signals builds the training set and serves the live value from one definition, so what the model learned from is what it reads at inference.

[Start free](https://signals.snowplow.io/start) [Talk to an engineer](https://signals.snowplow.io/start?intent=engineer) 

The real engine · no card · no sales call

![One Signals definition, card_attempts_session, branches into a point-in-time training set of past values and outcome labels and a live value of 4 for this session, and both feed the same fraud model.](https://signals.snowplow.io/images/products/hero-model-features.webp)

One definition. training and serving read the same thing

[ Try it on yourself ↓ ](#live-panel) 

Below is your own visit to this page, computed by Signals as you read.

## Signals, about you 

connecting 

What Signals knows about your visit, right now 

Signals is computing your first attributes from the events this page just sent.

Every highlighted part is an attribute Signals computed from the behavioral data your browser sent during this visit. Open the Product menu above and watch the sentence change.

Show me how Signals knows this

Keyed on an anonymous session id. Signals drops these values a day after your last event. 

Why it usually fails

## Notebook features stall on the way to production. 

Someone rewrites the feature for serving, the two drift apart, and the model degrades without anyone noticing.

**Two versions of every feature**The notebook says one thing. Production says another.

**Training data that peeks ahead**Computed over the whole session, it leaks the outcome.

**A ticket per feature**Each new one waits in the data engineering queue.

What you build with it

## Models that score this session, on the features they learned from. 

Each of these needs the feature current to the last event at inference, and the same feature as it stood at each past moment for training.

Propensity 

### Higher model lift

The score runs on features from before the session. Signals serves the same features current to the last event, so the score can still change the outcome.

Ranking 

### Offline gains that hold online

The ranker trains on features production cannot reproduce. Signals builds both from one definition, so what you measured offline is what you get live.

Fraud and abuse 

### Lower losses before payout

Abuse is caught in the next review, after the money has moved. Signals serves this session's behavior to your model at request time, so it scores before the payout.

What you build

## Define once. Train on history, serve on the stream. 

01 · Collect 

### Add a Snowplow SDK

Web, mobile or server. Events arrive validated against your schemas, so every feature reads clean, typed properties.

02 · Define 

### Write the feature as an attribute

Signals calls each feature an attribute. Counts, recency and order over your events, keyed on user, session or listing.

03 · Train 

### Build the training set from the same definition

Name the outcome. The dataset builder labels your history and computes each attribute as it stood at that moment, into a table in Snowflake.

04 · Serve 

### Read it at inference from the streaming engine

One call returns every feature in the service, in 6ms p50, in-region.

![One session_features attribute group, holding failed_searches_session, feeds both a point-in-time training set in Snowflake built by the dataset builder, with each row's value as of that moment and its outcome label, and the live value read from the ranker_features service with get_service_attributes and passed to model.predict.](https://signals.snowplow.io/images/products/usecase-model-features.webp)

Step by step: [Score prospects with a live model →](https://docs.snowplow.io/tutorials/signals-ml-prospect-scoring/intro/) The background: [Feature stores, explained →](https://signals.snowplow.io/learning/feature-stores) 

Works with 
* Snowflake
* Databricks
* BigQuery
* Vertex AI
* Amazon Bedrock

The code

## The same attribute group, in the training set and at inference. 

The Python SDK builds a point-in-time correct training set from your attribute groups, then reads the live values from the service that holds those same groups.

First, give your agent the Signals skills 

$ `npx plugins add snowplow/skills` Copy Copied 

Write it yourself

```
from datetime import datetime, timezone
from snowplow_signals import AtomicProperty, Criteria, Criterion, Signals, TrainingSpan

sp_signals = Signals(api_url=api_url, api_key=api_key, api_key_id=api_key_id, org_id=org_id)

# Training: one row per labeled moment, features from only the events before it.
run = sp_signals.submit_dataset_run_with_session_anchors(
    attribute_groups=[session_features],
    goal_criteria=Criteria(all=[
        Criterion.eq(AtomicProperty(name="event"), "transaction"),
    ]),
    training_span=TrainingSpan(
        start_time=datetime(2026, 1, 1, tzinfo=timezone.utc),
        end_time=datetime(2026, 4, 1, tzinfo=timezone.utc),
    ),
)

# Inference: the same features, current to the last event.
features = sp_signals.get_service_attributes(
    name="ranker_features",
    attribute_key="domain_sessionid",
    identifier=session_id,
)
score = model.predict(features)
```

Or hand your agent this prompt

Add Snowplow Signals to this model's pipeline so training and serving use one feature definition. Rewrite the session features from our notebook as a Signals attribute group, build the training set with submit_dataset_run_with_session_anchors using our conversion event as the goal, and replace the serving path's feature code with get_service_attributes. Keep the model and its hyperparameters as they are, so the only thing that changes is where the features come from.

The dataset builder supports Snowflake today. You can run a managed build, or generate the SQL and run it yourself.

The feature: [Real-time attributes →](https://signals.snowplow.io/products/real-time-attributes) Full reference: [Create ML training datasets →](https://docs.snowplow.io/docs/signals/ml-training-datasets/) 

What changes

## The model sees what it was trained on. 

1 definition 

Shared by the training set and live serving

0 copies 

Second implementation of a feature for your team to maintain

6ms 

Added at inference, p50 in-region

Questions

## Before you move a feature over

### Is this a feature store?

It does the serving half of one for behavioral features, and it builds the training set from the same definitions. It starts from the events, so it collects them too. If your features come from other sources, a general feature store may suit you better.

### Do I have to replace the feature store I run?

No. A common pattern is Signals for behavioral features on the request path and your existing store for everything else.

### How does it stop training data leaking the outcome?

The dataset builder computes each attribute from only the events before the moment you are predicting from, using the same definitions the live path reads. Nothing that happened afterwards reaches the training row.

### Which warehouses does the dataset builder support?

Snowflake today. Attribute backfill, which fills history into the live store, also runs from BigQuery and Databricks.

### Do I need an event stream already?

No. Collection is part of Signals. Add a Snowplow SDK and events start flowing. If you already run Snowplow, Signals reads the pipeline you have.

### Where does it run?

Managed SaaS, or a private deployment in your own AWS or GCP account. Same architecture either way.

### Related use cases

[In-session personalizationRank against what this customer is doing in this visit, while they are still on the page.](https://signals.snowplow.io/use-cases/in-session-personalization) [Behavioral memory for AI agentsThe agent remembers what the customer did this session, beside what they said.](https://signals.snowplow.io/use-cases/customer-aware-agents) [State for System One modelsA typed decision is only as good as the state you send it.](https://signals.snowplow.io/use-cases/system-one-models) 

## Move one feature out of the notebook. 

Define one feature as an attribute, build a training set from it, then read the same value live for your own sessions. The free tier runs on the real engine: no card, no sales call.

[Start free](https://signals.snowplow.io/start) [Talk to an engineer](https://signals.snowplow.io/start?intent=engineer) 

Evaluating? [Signals vs a feature store →](https://signals.snowplow.io/evaluate/feature-stores)
