Run ML algorithm inside map function in Spark
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
You can run machine learning code inside a Spark transformation, but the right pattern depends on whether you are doing inference or training. Per-record inference can live inside map or, more efficiently, mapPartitions. Training a separate model inside each map call is usually a design mistake because it destroys batching, wastes startup time, and fights Spark’s execution model.
Use Spark for Distributed Data, Not Tiny Per-Row Model Creation
The basic anti-pattern is creating or training a model for every element.
That causes repeated model construction, heavy serialization costs, and poor use of executors. Spark is good at moving a function over partitions of data. It is not good at turning every row into a separate machine-learning job.
The usual good pattern is one of these:
- train a model once and use Spark for distributed inference,
- load a model once per partition and score records in that partition,
- or use Spark MLlib so training itself is expressed as a Spark job.
For Lightweight Inference, Broadcast the Model
If the model is small and serializable, broadcasting it can work well.
This works because the model is small enough to ship to executors and cheap enough to run per record. It is a reasonable pattern for classic tabular inference.
Prefer mapPartitions When Model Setup Is Expensive
If loading the model takes noticeable time, do not do it once per row. Do it once per partition.
The example is intentionally simple, but the structure is what matters. In real code, score_partition would load a model once, process all rows in the iterator, and yield predictions. This is usually the right place for deep-learning inference or any model with nontrivial initialization cost.
Use Spark ML APIs for Training When Possible
If you truly want distributed training over Spark data, prefer Spark-native algorithms or frameworks that integrate explicitly with Spark. That keeps optimization, shuffling, and aggregation aligned with Spark’s execution engine.
Trying to call a standalone training routine inside map usually creates many unrelated local models instead of one global model. Unless that is your actual goal, it is the wrong abstraction.
A quick rule is:
- use
mapormapPartitionsfor inference, - use MLlib or another integrated training framework for training,
- and only train per partition when your use case truly wants one local model per partition.
Watch Serialization and Dependency Boundaries
A model object that works locally may fail on executors because it cannot be pickled cleanly, because a native dependency is missing, or because version differences exist between driver and workers. That is why Spark inference jobs should be tested in an environment that resembles the actual cluster, not only in local mode.
Also remember that Python UDF overhead, JVM-to-Python boundaries, and model size can dominate runtime. Sometimes the right optimization is not changing the mapping function. It is changing how and where the model is served.
Common Pitfalls
- Training a new model inside every
mapcall. - Broadcasting a large model that should instead be loaded once per partition.
- Assuming local tests prove cluster serialization and dependency setup are correct.
- Using per-row Python inference when vectorized or partition-based scoring would be much cheaper.
- Treating Spark as a general task queue instead of a distributed data engine.
Summary
- Running ML code inside Spark is normal for inference, but not all placements are equally efficient.
- '
mapis acceptable for cheap scoring functions;mapPartitionsis better when model setup is expensive.' - Broadcast small, serializable models for simple inference workflows.
- Use Spark-native ML tooling for distributed training rather than training inside
map. - Optimize around executor setup, serialization, and partition behavior, not just the prediction function itself.
Related reading
- Running dependent hadoop jobs in one driver
- Running Tensorflow on big data
- Save null Values in Cassandra using DataStax Spark Connector
- Scaling out with 200+ Kafka topics
- Running Adam Optimizer
- Running time of algorithm A is at least On² - Why is it meaningless?
- Schedule each Apache Spark Stage to run on a specific Worker Node
- Sending Large CSV to Kafka using python Spark

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.