Feature stores occupy a strange place in the ML stack: everyone agrees they solve a real problem, and many teams that adopt an off-the-shelf one end up fighting it. The open-source standard, Feast, is capable and well-designed - and yet a recurring story is teams evaluating it, hitting friction with their specific requirements, and building a lighter store of their own. Understanding what a feature store actually does, and where the genuinely hard part lives, explains both why you might skip Feast and what you'd have to get right if you did.
What a feature store actually does
Strip away the marketing and a feature store solves two concrete problems. First, training/serving consistency: the features a model trained on must be computed identically when it serves predictions, or the model silently degrades. Second, reuse: features defined once should be usable across models and teams instead of re-implemented (and subtly diverging) each time. A feature store is the system that defines features once and serves them both to training (historical, point-in-time) and to inference (fresh, low-latency). What it is not is magic - it doesn't engineer features for you or fix bad ones.
Why teams skip Feast
Feast is a framework with opinions, and the friction usually comes from the gap between its model and a team's existing infrastructure. Common reasons teams build their own: they already have most of the pieces (a warehouse for offline, a key-value store for online) and Feast would add a layer rather than replace one; their requirements are narrower than Feast's generality and a focused build is simpler to operate; or integrating Feast with their specific stack turned out to be more work than building the slice they actually needed. The decision isn't "Feast is bad" - it's "the 20% of a feature store we need is cheaper to build than to adopt a general framework for."
A three-layer architecture
A from-scratch feature store typically has three layers. An offline store (usually the data warehouse) holds the full history of feature values for generating training data. An online store (a low-latency key-value store like Redis or DynamoDB) holds the latest feature values for serving predictions fast. And a feature server / API sits in front, giving models a single way to fetch features for inference. The pipelines that compute features write to both stores, keeping them in sync.
The hard part: point-in-time correctness
Here is where feature stores earn their existence, and where naive implementations introduce silent bugs. To build training data, you must join each label to the feature values as they were at that moment - not as they are now. If a model is trained on a feature's current value but that value reflects information from after the prediction time, you've leaked the future into training, and the model looks brilliant in evaluation and fails in production. Point-in-time correct joins - fetching each feature's value as of the label's timestamp - are the non-negotiable hard requirement of any feature store, home-built or not. Getting this wrong is the most common and most damaging feature-store bug.
Freshness: batch vs streaming
Features update on different clocks. Some are fine computed nightly in batch; others (a user's last-five-minutes behavior) must update in near real time via a streaming path. A practical store supports both - batch pipelines for slow-moving features, streaming for fresh ones - writing both to the online store so serving sees current values. Matching each feature's update path to how fresh it must be is a core design decision, not an afterthought.
The takeaway
A feature store is, at its core, the discipline of defining features once and serving them consistently to training and inference, with point-in-time correctness as the part that must not be wrong. Whether you adopt Feast or build your own comes down to fit: a general framework earns its keep when your needs are broad and you lack the pieces, and a focused build wins when you already have the warehouse and key-value store and only need the thin layer that ties them together with correct point-in-time joins. Either way, the lesson is the same - the architecture is the easy part; the temporal correctness is the part that decides whether your models work in production.
Leave a Comment