×marble
all posts
Jun 12, 2026·12 min read

Real-Time vs Batch Personalization: Pick the Right Mode Per Surface

Not every surface needs real-time personalization. The right framework for picking real-time vs batch per surface, with latency, cost, and freshness math.

Alex Shrestha·Founder, ×marble

Real-Time vs Batch Personalization: Pick the Right Mode Per Surface

TL;DR.

  • Real-time vs batch personalization is not a platform decision; it is a per-surface decision, and most teams that pick one mode globally are either burning money or shipping stale recommendations.
  • The right surface-by-surface defaults in 2026 are: home page batch (refresh every 1-6 hours), category page near-real-time (refresh per session), product page real-time (intent shifts in seconds), search real-time (the query itself is fresh signal), email batch (sent once anyway), push-notification micro-batch (segment refresh hourly, send-time real-time).
  • The cost ratio between real-time and batch infrastructure for the same recommendation workload is typically 10-50x at steady state, driven by always-on stream processors, low-latency feature stores, and 24/7 on-call.
  • Hybrid is the production answer: batch computes expensive collaborative-filtering and graph features overnight; streaming layers session intent on top in <30 ms. Lambda-shaped, not Kappa-shaped, for most teams.
  • The hardest part of the decision is not picking a mode — it is naming the freshness SLO per surface and writing it into the spec before anyone codes. If your spec says "as fresh as possible," the cost will be "as expensive as possible."

The single most expensive architecture mistake we see in personalization in 2026 is teams making this a binary choice. They read a Databricks case study about millisecond personalization, decide their site needs to be "real-time everywhere," and then spend a year and seven figures rebuilding a stack to refresh a home page that nobody scrolls past anyway. They were not wrong about real-time. They were wrong about everywhere.

This post is a surface-by-surface framework for picking real-time vs batch personalization. We'll work through six surfaces with their freshness requirements, the latency math behind each one, the cost ratio you should expect when you flip a surface from batch to real-time, and the hybrid patterns that let you have the right mode on the right surface without running two separate stacks. By the end you should be able to draw the freshness/cost grid for your own product on a whiteboard and defend each cell.

The freshness SLO is the decision, not the mode

Before any architecture argument, agree on the contract. Real-time vs batch personalization is downstream of a single number per surface: the freshness SLO. That is the maximum age of the signal that informed the recommendation, measured from the moment the user takes the action to the moment the recommendation is rendered. If the SLO is "30 seconds," you need streaming. If it is "6 hours," you do not. Most teams skip this number because it forces them to admit that their home page does not need millisecond freshness, and admitting that forces a conversation about why they bought the streaming platform.

The honest taxonomy has three tiers, not two. Batch personalization refreshes on a schedule — hourly, daily, weekly — and the cost profile is whatever your warehouse charges to run a job. Near-real-time personalization refreshes on a trigger (session start, page view, segment update) with a freshness SLO measured in minutes. Real-time personalization refreshes inline with the request, with the new signal in the same response, freshness SLO measured in seconds or sub-second. The DMA's breakdown of real-time, near-real-time, and batch personalisation is a reasonable industry reference for these tiers.

We design freshness per surface, not globally, because user expectations are surface-specific. On a product page, the user's intent has already shifted by the time the page loads — anything fresher than the click that brought them there is useful. On a home page, the user does not even remember what they did yesterday, so a 4-hour-old segment is indistinguishable from a 4-millisecond-old one. Spending streaming-grade infrastructure on home-page recommendations is paying for a property the user cannot perceive.

Surface-by-surface framework: when each mode wins

Here is the default we ship with new ×marble integrations. It is not law — your product can argue specific cells — but it is the right starting grid.

| Surface | Mode | Freshness SLO | Why | |---|---|---|---| | Home page | Batch | 1-6 hours | User intent at the home page is broad; batch CF features dominate | | Category page | Near-real-time | 1-15 minutes (per session) | Some intent has formed; session signal helps | | Product page | Real-time | <5 seconds | Intent is concrete; "users also viewed" should reflect last click | | Search results | Real-time | <1 second | The query IS the fresh signal; rank in same request | | Email | Batch | 1-24 hours | Email is composed once; freshness lives in send-time selection | | Push notification | Hybrid | Segment hourly; send-time real-time | Batch picks who gets a push; real-time picks what |

Home page personalization is the surface where batch wins cleanest. The user has not yet declared intent on this session, so the ranker is leaning entirely on long-horizon features — collaborative filtering, taste graphs, demographic priors. Those features are expensive to compute and stable over hours. Recomputing them per request burns money without changing the output. A nightly batch refresh (or every six hours for high-velocity catalogs) gives you 99 percent of the lift at 2-5 percent of the cost of doing the same work in real-time.

Product page personalization is the surface where real-time wins cleanest. The user just clicked into a specific item. The most predictive signal in the next request is the click that brought them to this page, not their behavior from yesterday. If your "frequently bought together" or "more like this" module is reading from a feature store updated nightly, you are throwing away the signal that matters most. A real-time recommendation engine here typically lifts conversion 15-30 percent over the batch equivalent — numbers we have seen consistently across our own deployments, and consistent with the ranges Databricks reports in the MakeMyTrip millisecond personalization case study.

Search is real-time by definition. The query string is the freshest possible signal — it did not exist five seconds ago. Trying to serve search results from a batch-precomputed index keyed by user means you are personalizing yesterday's queries, which is a category error. Search ranking can use batch features (the user's long-term preferences inform tie-breaking), but the candidate generation has to be inline with the query.

Email and push split differently. Email is batch even when it looks real-time, because the recommendation is composed once and serialized into an HTML body that ships to the user's inbox. Whatever model picked the products gets a several-hour head start on the user opening the email. Push notifications split: deciding who to push at all is a batch problem (a model that scores each user for likelihood of engagement), but deciding what to push at send time benefits from real-time signal (the user's last open, last interaction, current location). The hybrid pattern is one of the cleanest splits in the stack.

The cost ratio: real-time vs batch infrastructure

The reason this decision matters is that the cost delta between modes is not a 2x. It is, in practice, 10-50x at steady state for the same recommendation workload. The components that drive the multiplier are predictable:

  • Always-on streaming compute. A batch job runs for 30 minutes a day and shuts down. A streaming pipeline runs 24/7. That alone is a 48x ratio on compute hours, before any density argument. Branch Boston's real-time vs batch ML comparison makes the same point: batch can use spot instances and scheduled workloads; streaming demands always-on infrastructure.
  • Low-latency online feature stores. Batch jobs read and write to S3/object storage at a few cents per GB. Real-time recommendation engines need single-key reads in <5 ms, which means Redis, DynamoDB, or a managed online feature store. The per-GB cost ratio is typically 100-500x against the cold-storage equivalent, and personalization features are often multi-TB.
  • Engineering and on-call overhead. A batch pipeline that fails at 3 a.m. waits for the morning standup. A streaming pipeline that fails at 3 a.m. wakes someone up, because the product is degraded right now. The implicit on-call tax is often a quarter to a full FTE per stream you run in anger.
  • Training-serving skew prevention. When features must match across batch (training) and streaming (serving), the engineering discipline required to keep the two paths consistent is substantial. The cost is not in compute; it is in the senior engineering hours you spend writing the same transformation twice in different DSLs and reconciling them.
  • Observability. Streaming systems need percentile-bucket metrics, freshness lag tracking, watermark monitoring, and per-key heat maps. The Datadog / observability bill for a streaming stack is typically 3-10x what the equivalent batch stack costs to monitor.

You can reduce the ratio with care — Kappa-style single-pipeline designs, autoscaling stream processors, on-demand feature recomputation — but it is hard to get below 5-10x in production at meaningful scale. The right way to think about it is: every surface you move from batch to real-time is roughly an order of magnitude more expensive than the surface you started with. That is fine for surfaces where the lift justifies it, and disastrous for surfaces where it does not.

The hybrid pattern: Lambda-shaped pipelines

The production answer for most teams is hybrid, not all-real-time or all-batch. The shape is Lambda — a batch pipeline that computes expensive features overnight (collaborative filtering vectors, graph embeddings, segment memberships) plus a streaming layer that overlays session intent on top in real-time. We covered the four-layer Score/Graph split in the reference architecture for real-time personalization; hybrid is what that architecture looks like when you flip on the freshness budget per surface.

The Lambda pattern is unfashionable — Kappa promised a simpler single-pipeline future — but Lambda survives because the two workloads are genuinely different. Computing user embeddings over 90 days of history is a batch problem and always will be. Reflecting the user's last three clicks in the next request is a streaming problem and always will be. Pretending these are the same problem to fit a single-pipeline aesthetic costs more engineering than it saves. The convotis writeup on event-stream-driven retail personalization is good on the streaming half; we'd add that the streaming half works because there is a batch half feeding it the long-horizon priors.

Concretely, the hybrid shape we recommend:

  1. Batch layer. Nightly job builds collaborative-filtering vectors, knowledge-graph embeddings, segment memberships, and any feature that requires a multi-day window. Writes to the offline feature store (training) and the online store (serving).
  2. Streaming layer. Consumes the event log, maintains per-user session state in Redis or a streaming-store. Computes session-level features — last N clicks, time-on-site, query history — with a freshness SLO of seconds.
  3. Score layer. At request time, joins the user's batch features (long-horizon) with their streaming features (session). Ranks candidates. The merge is the magic — and the place where training-serving skew lives if you are not careful.

For the freshness-vs-cost dial per surface, the home page reads only the batch slice; the product page reads both; the search page reads streaming-heavy with batch tie-breaking. Same pipeline; different reads per surface. That is what "right mode per surface" looks like in code.

When real-time is overrated (and when it is underrated)

Real-time is overrated when: the user's intent has not materially shifted since the last batch refresh (most home pages, most landing pages, most email composition); the product is content-light and not constantly changing (B2B documentation, slow-moving catalogs); the freshness SLO has never been written down (which usually means it does not actually matter to anyone). Spending streaming infrastructure here is paying for a property nobody can perceive.

Real-time is underrated when: the user just took a high-intent action and the next request should reflect it (add-to-cart, search query, item click); the catalog turns over fast enough that yesterday's recommendations are stale (news, social feeds, live events, marketplaces); the conversion event is close enough to the recommendation that latency hurts (checkout, cart, post-add cross-sell). For news especially — see personalization for news apps — the catalog churn is so fast that batch is structurally wrong even for the home page.

The mistake most teams make is choosing globally. The right move is choosing per surface, writing the freshness SLO into the spec, and letting the architecture follow.

How ×marble fits in

If you would rather not stand up a Lambda-shaped batch-plus-streaming stack yourself, ×marble ships exactly this hybrid: a knowledge graph that holds batch-refreshed user state plus a streaming overlay that captures session intent in <30 ms p99. The API you call is the same regardless of surface; you tell us the freshness SLO per surface, and we read the appropriate slice. Same engine powers three of our own surfaces with very different freshness profiles: Vivo (daily AI briefings, batch-refreshed overnight), Video (real-time YouTube surface, session-aware), and Music (Spotify/Apple Music personalization, fully streaming). One graph; three freshness contracts; three surfaces. That is the surface-by-surface framework in production.

FAQ

What is the difference between real-time and batch personalization?

Real-time personalization computes and serves recommendations inline with the user's request, typically in <100 ms end-to-end, using signals as fresh as seconds old. Batch personalization precomputes recommendations on a schedule — hourly, daily, or weekly — and serves them from a cache. The difference is freshness: real-time reflects the user's current session; batch reflects what was true at the last refresh.

When should you use batch personalization instead of real-time?

Use batch personalization when the freshness SLO for the surface is measured in hours or longer — typical for home pages, marketing emails, segment-based audiences, and most B2B applications. Batch is also the right call when the predictive features are inherently long-horizon (collaborative filtering, long-tail preferences) and do not change meaningfully session over session. The cost ratio favors batch by roughly 10-50x for the same workload.

What does real-time vs batch personalization cost?

Real-time recommendation engine infrastructure typically costs 10-50x more than the batch equivalent for the same workload, driven by always-on streaming compute, low-latency online feature stores, 24/7 on-call coverage, and observability overhead. The ratio can be reduced with Kappa-style single-pipeline designs and autoscaling, but the floor in production is usually 5-10x. The freshness vs cost personalization trade-off is the dial most teams underestimate.

Is batch vs streaming personalization a platform decision or a per-surface decision?

It is a per-surface decision. Most production systems run a hybrid Lambda-shaped pipeline: a batch layer that computes expensive long-horizon features overnight, and a streaming layer that overlays session intent in real-time. Each surface reads the slice it needs — home page reads batch only, product page reads both, search reads streaming-heavy. Choosing globally between batch and streaming is the most common architecture mistake we see.

What is the freshness SLO for personalization?

The freshness SLO is the maximum acceptable age of the signal that informed a recommendation, measured per surface. For product pages and search, it is typically <5 seconds. For home pages and email, it is 1-24 hours. The SLO drives every architecture decision downstream: streaming vs batch, online vs offline feature store, real-time vs precomputed ranking. If your spec does not name a freshness SLO per surface, the architecture will default to the most expensive option.

Further reading

the product behind these notes

×marble is the personalization graph.

One API. A living knowledge graph per user. Day-zero ready, explainable by construction. We built it so you don't have to.

See ×marble