Anomaly detection is latency-sensitive in a way that most supervised learning use cases are not. A fraud model scoring a transaction or a network intrusion model evaluating a connection attempt both need to answer the same question: does the current observation look different from the recent past? If "the recent past" means the last batch run, the answer is frequently wrong.
The feature pipeline is almost always the binding constraint. The model inference itself is fast, measured in milliseconds. The question is whether the features the model reads at inference time reflect the world as it was seconds ago or as it was 15 minutes ago.
This post walks through the design choices that matter when building feature pipelines for anomaly detection workloads, and where the tradeoffs land.
Why Anomaly Detection Has Different Freshness Requirements
Most ML use cases tolerate stale features. A recommendation model predicting what a user might want to read uses features like "most viewed categories last 30 days" and "average session length last week." These features change slowly, and a batch pipeline running twice daily is fine.
Anomaly detection is different because the baseline the model uses to judge "normal" must be current. The features that constitute "normal behavior" for a given entity shift continuously. An API client that usually sends 10 requests per minute is anomalous at 10,000 per minute. A user who typically logs in from one city is anomalous when their session appears simultaneously in two continents. But a nightly batch pipeline will show a user's most recent location as the city where they logged in last night, not where they are right now.
The signal that makes anomaly detection work is the deviation from a current baseline, not a deviation from a historical average. This is why feature freshness for anomaly detection is not a nice-to-have; it is a fundamental requirement of the approach.
What "Low Latency" Actually Means in This Context
Before diving into architecture, it is worth being precise about what latency you are measuring. In a feature pipeline for anomaly detection, there are at least three latency components:
Event ingestion latency. How long does it take for an event that occurred in the world to arrive in your streaming source? For Kafka-based pipelines with producers writing directly, this is typically sub-second. For CDC-based pipelines reading from a database's replication log, this is sub-second as well but can spike under heavy write load. For pipelines pulling from object storage or log collectors, this can be minutes.
Feature computation latency. How long after an event arrives in the streaming source does it take for the affected feature values to be updated? For incremental computation, this is the time to propagate the delta through the operator graph and write the result, typically tens of milliseconds. For batch computation, this is the batch interval: 5 minutes, 15 minutes, or hours.
Feature serving latency. How long does it take for a model serving request to read the updated feature value? This is determined by the feature store's read path: point query latency on Redis or similar is sub-millisecond; a read that hits a cache TTL and falls back to the database adds the fallback latency.
When teams say their anomaly detection pipeline is "real-time," they usually mean the inference is fast. The feature computation latency is often overlooked until something obvious slips through the model.
Structuring Features by Their Update Rate
Not all features in an anomaly detection pipeline need to be computed with the same freshness. Treating every feature as requiring sub-second updates wastes compute and adds operational complexity. The right approach is to segment features by their staleness tolerance and use different computation mechanisms for each class.
Consider a network anomaly detection system monitoring API traffic. The features fall into roughly three classes:
Velocity features (seconds-to-minutes staleness tolerance). Request rate per client in the last 60 seconds, error rate in the last 5 minutes, distinct endpoint count per IP in the last hour. These are the features where anomalies manifest first and where freshness matters most. They should be computed incrementally.
Behavioral baseline features (minutes-to-hours tolerance). Average request rate per client in the last 24 hours, historical endpoint distribution per client, typical session duration. These change more slowly and can be computed on a 15-30 minute batch cadence without meaningful accuracy loss.
Entity metadata features (days tolerance). Account age, subscription tier, geographic registration, historical anomaly flag counts. These change rarely and are best computed nightly and served from a static lookup table.
By segmenting features this way, you only need the incremental computation infrastructure for the first class, which is typically 20-30% of your total feature set. The remaining 70-80% can stay on a batch pipeline. The model reads from both sources at inference time, getting sub-second freshness where it matters and batch freshness where it is sufficient.
Building the Incremental Layer
For the velocity and near-real-time features, the pipeline design is straightforward: events flow from the source system into a Kafka topic, a Feldera pipeline reads from that topic and maintains a set of materialized views, and those views are written to a low-latency read store (Redis or a similar key-value store) for serving.
-- API anomaly features: rate and error signals per client
CREATE MATERIALIZED VIEW client_rate_features AS
SELECT
client_id,
COUNT(*) FILTER (WHERE event_ts >= NOW() - INTERVAL '1 minute') AS req_1m,
COUNT(*) FILTER (WHERE event_ts >= NOW() - INTERVAL '5 minutes') AS req_5m,
COUNT(*) FILTER (
WHERE event_ts >= NOW() - INTERVAL '5 minutes'
AND status_code >= 500
) AS errors_5m,
COUNT(DISTINCT endpoint) FILTER (
WHERE event_ts >= NOW() - INTERVAL '1 hour'
) AS distinct_endpoints_1h
FROM api_requests
GROUP BY client_id;
Each new API request event triggers a delta update through this view. Only the affected client_id's row changes, and only the affected window counters need to be recalculated. There is no full table scan, no batch trigger, and no scheduling overhead.
Correctness Under Backpressure
One question that comes up in production: what happens to feature correctness when the pipeline falls behind? If the Kafka consumer group lag grows because the upstream event rate spikes, the incremental pipeline is processing events that are older than their timestamps suggest. The features it writes may reflect a delayed view of reality rather than the current one.
This is the same problem batch pipelines have, but more visible in an incremental context because the freshness guarantee is a key part of the value proposition. The right approach is to monitor consumer group lag on the feature-computation consumer group and treat sustained lag as a pipeline health alert. For burst traffic that clears within seconds, the lag is self-correcting. For sustained load above the pipeline's throughput capacity, scaling is required.
Incremental computation has a significant advantage here over batch: the pipeline can process the backlog without a full recompute. As events drain, the aggregates converge to the correct current state automatically. A batch pipeline catching up from a 30-minute backlog must recompute the entire 30-minute window; an incremental pipeline processes each event in the backlog as a delta, applying only its marginal contribution to the running state.
The Boundary Between Incremental and Batch Features
Incremental computation is not always the right answer for anomaly detection features, and it is worth being explicit about where it breaks down. Features that require access to a very long historical window (90 days of activity, lifetime aggregate counts, rolling baselines computed over months) are expensive to maintain incrementally because the state size grows with the window length. For these features, a daily batch job reading from a data warehouse is usually more cost-effective. The staleness acceptable for a 90-day rolling baseline is measured in hours or days, not seconds.
Similarly, if your anomaly detection model uses complex learned baselines (an autoencoder trained on historical behavior, a neural network that produces a latent representation of "normal"), those are not features you can compute incrementally with SQL. They require periodic model inference over a batch of historical data. The incremental layer feeds into these as inputs, but the learned baseline itself is recomputed on a slower cadence.
The practical design principle is: use incremental computation for features that change meaningfully within the model's decision window, and use batch computation for everything else. The decision window for real-time anomaly detection is typically seconds to minutes. Any feature whose value would change by a significant amount within that window relative to its normal variation range is a candidate for incremental computation. Everything else is not.