Skip to main content

Module 8 — Features shared across teams

A feature store where only one team publishes features is a data pipeline with extra steps. The store's real value shows up when a second team asks for a feature the first already has. This module is about that second team, and what changes in the organization to make sharing safe rather than negotiated ad hoc.

The situation, on the fraud thread

The fraud team has published card_activity_7d with an avg_amount_last_7d field it uses in the scoring model. Weeks later the marketing team designs a retention campaign around "high-value customers over the last week" and needs exactly that number.

Three options are on the table.

Recompute it themselves. They open a notebook, write their own window aggregate, and get a number that mostly matches the fraud one — except on 3 % of cards where the two implementations differ (module 1's five 1 % gaps again). Two months later a compliance auditor asks why the same customer has two "average weekly spend" numbers in two dashboards.

Ask the fraud team for a CSV. The fraud team dumps the last 90 days into a shared bucket, weekly. The marketing team now has a feature that is at best a week old, that stops being refreshed as soon as the fraud engineer leaves, and that no one owns.

Read the feature from the store. They add card_activity_7d:avg_amount_last_7d to their model's feature list. Same values as the fraud model, same freshness, same owner. If the fraud team materially changes the semantics, both teams see it at once, and the versioning discipline of module 4 says the fraud team must add _v2 rather than break the marketing team.

The third option is what the store exists to make possible. The first two are what happens when it doesn't exist, or when nobody knows what is in it.

Discovery is a first-class feature of the store

The store is only reusable if a second team can find what the first published. Feast, Tecton and Hopsworks all expose the registry as a queryable catalogue.

from feast import FeatureStore

fs = FeatureStore(repo_path=".")

for fv in fs.list_feature_views():
print(fv.name, "-", fv.description or "(no description)")
print(" owner:", fv.owner)
print(" tags:", fv.tags)
print(" fields:", [f.name for f in fv.schema])

For a human interface, feast ui starts a small web app that browses views, sources, entities and their lineage. Tecton and Hopsworks ship richer catalogues with search, faceted filtering on tags, and lineage graphs down to source tables.

Two disciplines make discovery work. Description fields must not be empty. A view called card_activity_7d with description="" is invisible to anyone who does not already know it exists. Tags must be a controlled vocabulary. domain: fraud, domain: marketing, pii: false, freshness: 15min — if every team invents its own tag namespace, filters become useless.

Documentation lives next to the definition

The feature view file is the right place for documentation, because it is where the code lives:

card_activity_7d = FeatureView(
name="card_activity_7d",
entities=[card],
ttl=timedelta(days=1),
schema=[
Field(
name="avg_amount_last_7d",
dtype=Float64,
description=(
"Average authorized transaction amount over the trailing 7 days. "
"Currency: EUR. Excludes declined and reversed transactions. "
"Refreshed every 15 minutes."
),
),
],
source=tx_source,
owner="team-fraud@example.com",
tags={"domain": "fraud", "pii": "false", "freshness": "15min"},
description=(
"Card behavior aggregates over the trailing 7 days, computed from the "
"same authorized-transactions source used by the fraud scoring model."
),
)

Three questions the description must answer, or the marketing team cannot safely reuse the feature: what does it count, in what unit, excluding what.

Ownership and governance, in practice

The owner of a shared feature is a team, addressable by email or Slack channel, not a person. That is not decoration; it is what allows on-call to reach someone when a materialization job breaks at 3 a.m. and what allows a downstream team to negotiate a change.

Governance answers three concrete questions.

Who can consume this feature? By default, everyone in the organization. Restrict only when a regulatory reason applies — for instance, features derived from personal data that are subject to per-purpose access controls. Feast enforces this at the network layer; Tecton and Hopsworks provide feature-level ACLs.

Who can change this feature's definition? Only the owner team, through code review on the repository. feast apply on a shared registry should be gated behind a merge to the main branch; direct apply from a developer's laptop is what makes silent semantic drift possible.

Who is warned when it changes? Every consumer team, from the registry's dependency graph. feast plan output on a pull request should list the models that read the affected view, so the review can include the consuming teams by name.

The cost of duplication avoided

Sharing has a measurable payoff, and quantifying it is often what wins the store its budget.

On the fraud thread, we counted seven features present in both the fraud and marketing pipelines before the store was in place: activity aggregates over 1 h, 24 h, 7 d and 30 d, average amount, distinct merchants, share of night-time transactions. Each was implemented twice — two pipelines, two schedules, two on-calls, two sets of tests, two audits. Consolidating them removed roughly 40 % of the compute cost across the two teams, and one full-time engineer's worth of maintenance.

The compute number is a bonus. The real gain is coherence. When the fraud dashboard and the marketing dashboard both display "average weekly spend" for the same customer, they now display the same number. That is not a technical property; it is a business one, and it is what an executive committee actually notices.

A store without a discovery habit is a store no one uses

The most common failure mode of feature stores is not the technology; it is the discovery gap. Teams keep recomputing what already exists, because they do not know it exists. Two habits fix it: every new model starts with a search in the registry ("does something like this already exist?"), and every new feature is announced in a shared channel with its tags. Without those habits, the store becomes a private database per team, which is exactly what it was supposed to prevent.

Summary

  • The store's real value shows up on the second consumer: sharing avoids parallel implementations that silently disagree and lets teams inherit each other's freshness and ownership.
  • Discovery is a first-class feature — non-empty descriptions, controlled tags, a browsable registry — and without it the store is invisible to potential reusers.
  • Ownership is a team, not a person; governance answers who consumes, who changes and who is warned when a definition evolves.
  • The measurable payoff is compute and maintenance saved, but the real payoff is coherence across dashboards and models, which is what stakeholders actually see.

Next module: monitoring feature quality upstream of the model, so you catch a drifting feature before it drifts a prediction.