Push sources and velocity features
For the complete documentation index see: llms.txt
All documentation pages available in markdown.
This page explains how PushSource and store.push() keep velocity features fresh, why aggregation happens outside Feast, and how to align TTL with your rolling window length.
Write and read paths
Feast splits the work in two. A background process computes the rolling aggregates and writes them into Aerospike with store.push(). At scoring time, Feast reads back whatever value that process wrote most recently.
| Path | Who computes aggregates | Feast API |
|---|---|---|
| Write (freshness) | Your background process (a Kafka consumer, Flink job, or timed script) | store.push() |
| Read (scoring) | No aggregation. Reads stored values. | get_online_features() |
Feast performs no aggregation on the read path, which is what keeps scoring fast: the model pays for a stored-value read instead of a computation over the account’s recent transactions. In exchange, the background process owns freshness. Feast cannot tell whether the value it read was written a second ago or an hour ago, so every write carries an event timestamp recording when the velocity snapshot was computed. Scoring code and monitoring compare that timestamp against the maximum age the model accepts.
TTL alignment
Stale velocity features can produce incorrect fraud scores without any pipeline error. Two separate settings limit how old a value can be. They live in different files and do different jobs.
| Setting | Where you set it | What it controls |
|---|---|---|
FeatureView.ttl | The ttl argument on the FeatureView in fraud_repo.py | Materialization lookback and historical point-in-time retrieval. Standard Aerospike online reads do not use it to reject an old stored value. |
ttl_seconds | The online_store block in feature_store.yaml | How long Aerospike keeps a record before expiring it. Aerospike applies it to the whole record on every Feast write. |
In this tutorial, ttl_seconds is ten minutes for a five-minute rolling window. The extra five minutes accommodates the interval between velocity snapshots. Choose the online-store TTL from your aggregation cadence and the maximum age your model accepts. For how expiration works in Aerospike, see Expiration (time to live).
Collocation on push
Push feature views use the same record layout as materialized ones. Feature views that share an entity and resolve to the same namespace colocate on one Aerospike record, and each store.push() updates only the map entries belonging to the feature view it targets. For the layout itself, see Namespace overrides and collocation and How materialization writes work in Tutorial: Serve real-time Feast features with Aerospike.
What collocation changes for push is expiry: views on one record share a single record-level TTL, so writing any one of them refreshes the expiry for all of them. The presence of a record therefore does not prove that every view stored on it is current.
Production streaming pattern
The manual push in this tutorial verifies the data contract: define, push, read back. It does not verify event consumption, rolling-window state, retries, or recovery after the aggregator falls behind. Those are responsibilities of the production stream job.
A Kafka consumer, Apache Flink job, or Spark Structured Streaming job can maintain per-account rolling windows and call store.push() on a flush interval for accounts that received new transactions.
Because neither Feast nor Aerospike can detect that an aggregator has stalled, production deployments monitor each feature view’s event timestamp rather than relying on record presence. A stalled aggregator keeps serving its last written value until the record expires, and a colocated view refreshed by another push extends even that deadline.
On the next page, you define fraud velocity features and push a velocity snapshot.