Skip to content

Serve features to a fraud model

For the complete documentation index see: llms.txt

All documentation pages available in markdown.

With the velocity snapshot pushed to Aerospike, you now read it back through the Python SDK and then through the feast serve HTTP feature server.

The record expires ten minutes after its latest write. If more than ten minutes have passed since the push, run python3 push_velocity.py again before continuing.

Read with the Python SDK

Read the velocity features through the fraud_scoring_v1 FeatureService to confirm the service abstraction works correctly.

  1. Create read_velocity.py:

    read_velocity.py
    from feast import FeatureStore
    store = FeatureStore(repo_path=".")
    features = store.get_online_features(
    features=store.get_feature_service("fraud_scoring_v1"),
    entity_rows=[{"account_id": "acct-1001"}],
    ).to_dict()
    print(features)

    store.get_feature_service("fraud_scoring_v1") passes the named service as the features argument. This is equivalent to listing "txn_velocity_5m:txn_count_5m", "txn_velocity_5m:amount_sum_5m", and "txn_velocity_5m:distinct_merchants_5m" explicitly, but keeps the feature list in the registry rather than scattered across scoring scripts.

  2. Run it:

    Terminal window
    python3 read_velocity.py
    Expected result
    {'account_id': ['acct-1001'], 'txn_count_5m': [7], 'amount_sum_5m': [1243.5], 'distinct_merchants_5m': [3]}

    Confirm that all three velocity fields match the values you pushed.

  3. Confirm the SDK read:

    • txn_count_5m is 7.
    • amount_sum_5m is 1243.5.
    • distinct_merchants_5m is 3.

Read through the feature server

feast serve starts a local HTTP server that exposes a /get-online-features endpoint. It lets non-Python services read features with a plain HTTP POST instead of importing the Python SDK.

  1. In a separate terminal, start the feature server from fraud-feast-demo:

    Terminal window
    feast serve

    The server listens on port 6566 by default. Leave it running for the curl step.

  2. Request features over HTTP:

    Terminal window
    curl -s -X POST http://localhost:6566/get-online-features \
    -H "Content-Type: application/json" \
    -d '{
    "feature_service": "fraud_scoring_v1",
    "entities": {"account_id": ["acct-1001"]}
    }'
    Expected result
    {
    "results": [
    {"values": ["acct-1001"], "statuses": ["PRESENT"], "event_timestamps": ["1970-01-01T00:00:00Z"]},
    {"values": [1243.5], "statuses": ["PRESENT"], "event_timestamps": ["2026-07-15T23:33:25Z"]},
    {"values": [7], "statuses": ["PRESENT"], "event_timestamps": ["2026-07-15T23:33:25Z"]},
    {"values": [3], "statuses": ["PRESENT"], "event_timestamps": ["2026-07-15T23:33:25Z"]}
    ],
    "metadata": {"feature_names": ["account_id", "amount_sum_5m", "txn_count_5m", "distinct_merchants_5m"]}
    }

    The event_timestamps in your output differ. The three velocity feature values (1243.5, 7, 3) should match what you pushed.

    Each entry in results corresponds to one name listed in metadata.feature_names. The first entry is the entity key (account_id), which carries the epoch timestamp 1970-01-01T00:00:00Z because entity keys are not time-stamped values. The three velocity features follow, each with the timestamp of the push.

    statuses reports PRESENT when Feast finds a stored value for that entity, or MISSING when no value is available (including after the Aerospike record expires).

  3. Confirm the HTTP read:

    • Response feature_names includes amount_sum_5m, txn_count_5m, and distinct_merchants_5m.
    • All statuses are PRESENT.
  4. Stop the feature server with Ctrl+C when finished.

In production, your fraud service calls the same get_online_features API (SDK or REST) at authorization time while a stream job keeps store.push() current on a flush interval.