So far in this course you have deployed models with basic containers and orchestrated them with Kubernetes fundamentals. This week we look at two production-grade serving systems that solve the scaling problem in very different ways: Ray Serve and KServe. Understanding both — and knowing when to reach for each — is one of the most practical architecture decisions you will make as an ML infrastructure practitioner.
Ray Serve is a scalable, framework-agnostic model serving library built on top of Ray. "Framework-agnostic" means it doesn't care whether your model is PyTorch, TensorFlow, or Scikit-Learn — or even whether it's a model at all. Ray Serve can just as easily serve arbitrary Python business logic (a validation step, a feature transform, a rules engine) alongside a model. Because deployments are defined directly in Python code, Ray Serve is especially well suited to composing complex, multi-model inference pipelines — for example, chaining a preprocessing step, an embedding model, a reranker, and a generation model — without ever leaving the Ray ecosystem or writing YAML. A common misconception is that Ray Serve can only run on Kubernetes. It cannot only run there — it runs on standalone Ray clusters, a single laptop, a VM, or on Kubernetes via the KubeRay operator. This flexibility is a real strength: you can prototype a serving pipeline on your laptop and later deploy the identical code to a Kubernetes cluster managed by KubeRay, with no rewrite.
Ray Serve LLM extends Ray Serve with OpenAI-API-compatible deployment, meaning existing clients written against the OpenAI SDK can point at your Ray Serve LLM endpoint with minimal changes. Critically, its autoscaler reacts to queue depth, not just CPU utilization — a much better signal for LLM workloads, where a handful of long-running generation requests can saturate a GPU while CPU usage looks unremarkable. New APIs in Ray Serve LLM support advanced distributed serving patterns built on vLLM, including prefill-decode disaggregation (splitting the compute-heavy prompt-processing phase from the memory-bound token-generation phase across different resources), data-parallel attention, and expert parallelism (for mixture-of-experts models). A recent HAProxy-based ingress upgrade to Ray Serve LLM delivers up to 5x higher throughput and 8x lower latency versus the prior proxy — a reminder that the ingress layer in front of your model matters as much as the model-serving logic itself. A second misconception worth correcting directly: students new to Ray Serve autoscaling often assume replica count reacts instantly to raw request counts, as if it were a simple thermostat. In reality, the Ray Serve autoscaler monitors queue sizes to decide how many replicas are needed, and then Ray has to provision the underlying actors (the worker processes that run your code) to match. That means scaling has multiple layers of latency: detecting a queue buildup, deciding to scale, and then waiting for new actors to start and load the model. Expect scale-up to take seconds to low minutes, not milliseconds.
KServe is a CNCF incubating project that provides the InferenceService custom resource definition (CRD) on Kubernetes. Where Ray Serve is a library you import, KServe is a Kubernetes-native abstraction: you declare an InferenceService object and KServe's controllers handle autoscaling, networking, health checks, and server configuration for you. KServe supports both predictive and generative model serving, with runtime support for Triton, Hugging Face Server, and others. This is the root of the most common misconception this week: assuming Ray Serve and KServe are direct substitutes solving the same problem the same way. They are not. Ray Serve is a general-purpose programmable library that can run anywhere — laptop, VM, or Kubernetes via an operator — and it excels at multi-model composition in code. KServe is built specifically around Kubernetes primitives (CRDs, controllers, the Knative-style serverless model) and excels when your organization's serving strategy is Kubernetes-first and you want infrastructure-level abstraction rather than code-level composition. For teams that need to serve many small models that change frequently, KServe offers an optional add-on called ModelMesh, enabled by annotating an InferenceService with serving.kserve.io/deploymentMode: ModelMesh. ModelMesh is designed for high-density, frequently-changing multi-model serving and supports a wide range of runtimes: TensorFlow, PyTorch, ONNX, scikit-learn, XGBoost, LightGBM, and OpenVINO IR.
| Factor | Choose Ray Serve | Choose KServe |
|---|---|---|
| Primary need | An all-in-one platform spanning training, tuning, AND serving | Kubernetes-native model serving only |
| Pipeline complexity | Complex, custom multi-model pipelines composed in Python | Standard single-model or ModelMesh-managed multi-model serving |
| Infrastructure | Multi-cloud, hybrid, or non-Kubernetes environments | Kubernetes-committed environments |
| Team background | Python/ML engineers comfortable writing serving logic in code | Platform/SRE teams comfortable with CRDs and Kubernetes operators |
| Model turnover | Moderate | Very high (many small, frequently swapped models via ModelMesh) |
The table above is a decision aid, not a rulebook — plenty of organizations use both, with KServe fronting stable production endpoints and Ray Serve powering experimental or pipeline-heavy workloads.
The throughline for this week: Ray Serve gives you programmable flexibility that runs anywhere, while KServe gives you Kubernetes-native standardization. Neither is objectively "better" — the right choice depends on your team's existing skills, your infrastructure commitments, and how complex your inference pipelines need to be. You'll get hands-on with both in this week's lab so you can feel the difference in developer experience firsthand, not just read about it.