How you serve predictions matters as much as model accuracy. Online serving returns predictions in milliseconds via API calls. Batch serving scores entire datasets on a schedule. Streaming processes events as they arrive. Each pattern has different latency, cost, and complexity profiles.
| Pattern | Latency | Use Case |
|---|---|---|
| Online (REST/gRPC) | <100ms | User-facing predictions, recommendations |
| Batch | Minutes–hours | Nightly scoring, report generation |
| Streaming | Seconds | Fraud detection, real-time pricing |
| Embedded | <1ms | On-device, edge inference |
A million customers could be scored; fifty thousand are looked up each day. A nightly batch scores all 1,000,000, and the average answer is 12 hours old when read. Online serving scores only the 50,000 that are asked for, with fresh inputs. Here 95% of the batch work is never read — but batch needs no low-latency service, and online does.
- The choice is about freshness and cost, not fashion: a credit limit that changes monthly gains nothing from online serving.
- Batch and online paths built separately drift apart (training–serving skew); share the feature code.
- Streaming is not free real time: it adds state, ordering and replay problems that batch never has.
entities = 1_000_000 # customers that could be scored requested = 50_000 # customers actually looked up per day batch = dict(scored=entities, avg_age_h=24 / 2) # nightly batch: everyone, results half a day old on average online = dict(scored=requested, avg_age_h=0) # online: only who is asked for, scored on the spot waste = 1 - requested / entities # share of batch scores nobody reads
Assumes import numpy as np and import pandas as pd. Each snippet carries its own example numbers; the comments say which are made up or simulated.
The same idea with a library
# Python — FastAPI online serving from fastapi import FastAPI import onnxruntime as ort import numpy as np app = FastAPI() session = ort.InferenceSession("model.onnx") @app.post("/predict") async def predict(features: list[float]): inp = np.array([features], dtype=np.float32) result = session.run(None, {"features": inp}) return {"prediction": result[0].tolist()}
- Designing Machine Learning Systems, C. Huyen, O’Reilly, 2022
- Designing Data-Intensive Applications, M. Kleppmann, O’Reilly, 2017
- D. Sculley et al., “Hidden Technical Debt in Machine Learning Systems”, Advances in Neural Information Processing Systems 28, 2015
Last reviewed October 2026 · How this site checks its content · Report a mistake