{"id":121154,"date":"2026-07-10T12:15:54","date_gmt":"2026-07-10T06:45:54","guid":{"rendered":"https:\/\/www.guvi.in\/blog\/?p=121154"},"modified":"2026-07-10T12:15:55","modified_gmt":"2026-07-10T06:45:55","slug":"ray-serve-tutorial","status":"publish","type":"post","link":"https:\/\/www.guvi.in\/blog\/ray-serve-tutorial\/","title":{"rendered":"Ray Serve Tutorial: How to Deploy Scalable ML Models with RayServe"},"content":{"rendered":"\n<p>Ray Serve is a scalable model serving library built on Ray. It helps developers turn Python functions, machine learning models, and AI pipelines into production-ready APIs. Ray Serve is framework-agnostic, so it can serve models built with PyTorch, TensorFlow, scikit-learn, Hugging Face, or custom Python code.<\/p>\n\n\n\n<p>A Ray Serve tutorial is useful when you want to deploy an ML model as an HTTP API, scale replicas, handle multiple requests, and move from local testing to production deployment.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>TL;DR<\/strong><\/h2>\n\n\n\n<ul>\n<li>Ray Serve helps you deploy machine learning models as scalable APIs.<\/li>\n\n\n\n<li>You define a deployment using @serve.deployment.<\/li>\n\n\n\n<li>You create an application using .bind().<\/li>\n\n\n\n<li>You run it locally using serve.run().<\/li>\n\n\n\n<li>FastAPI can be added using @serve.ingress() for clean API routes.<\/li>\n\n\n\n<li>Production deployments should use a Serve config file and serve deploy.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>What is Ray Serve?<\/strong><\/h2>\n\n\n\n<p>Ray Serve is a scalable model serving framework built on top of Ray, designed to deploy machine learning models, Python functions, and AI applications as production-ready APIs. It lets developers define deployments using Python classes or functions, expose them through HTTP endpoints, and scale them across CPU or GPU resources using Ray\u2019s distributed execution engine.<\/p>\n\n\n\n<div style=\"background-color: #099f4e; border: 3px solid #110053; border-radius: 12px; padding: 18px 22px; color: #FFFFFF; font-size: 18px; font-family: Montserrat, Helvetica, sans-serif; line-height: 1.6; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); max-width: 750px;\">\n  <strong style=\"font-size: 22px; color: #FFFFFF;\">\ud83d\udca1 Did You Know?<\/strong> \n  <br \/><br \/> \n  <strong style=\"color: #FFFFFF;\">Ray Serve<\/strong> is not limited to traditional ML models. It can serve <strong style=\"color: #FFFFFF;\">LLMs<\/strong>, stable diffusion models, object detection systems, and even plain Python functions, all through the same scalable <strong style=\"color: #FFFFFF;\">deployment framework<\/strong>.\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Key Ray Serve Functions<\/strong><\/h2>\n\n\n\n<ul>\n<li><strong>serve.deployment()<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Defines a <a href=\"https:\/\/www.guvi.in\/blog\/demystifying-python-class-methods\/\" target=\"_blank\" rel=\"noreferrer noopener\">Python class<\/a> or function as a Ray Serve deployment. It is the main decorator used to wrap model inference logic, API logic, or pipeline steps. A deployment can run with one or more replicas for scaling.&nbsp;<\/p>\n\n\n\n<ul>\n<li><strong>.bind()<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Creates a Ray Serve application from a deployment. It connects the deployment with its arguments and prepares it to be run using serve.run() or deployed through a config file.&nbsp;<\/p>\n\n\n\n<ul>\n<li><strong>serve.run()<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Runs a Ray Serve application locally or inside a Ray cluster. It accepts an application returned by .bind() and returns a handle to the ingress deployment.&nbsp;<\/p>\n\n\n\n<ul>\n<li><strong>@serve.ingress()<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Connects a Ray Serve deployment with a <a href=\"https:\/\/www.guvi.in\/blog\/upskilling-from-node-js-to-python-fastapi\/\" target=\"_blank\" rel=\"noreferrer noopener\">FastAPI app<\/a>. This is useful when you want clean HTTP routes such as \/predict, \/health, or \/classify.&nbsp;<\/p>\n\n\n\n<ul>\n<li><strong>num_replicas<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Controls how many copies of a deployment run at the same time. More replicas allow Ray Serve to process more requests in parallel.<\/p>\n\n\n\n<ul>\n<li><strong>ray_actor_options<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Defines compute resources for each deployment replica. It can assign CPUs, GPUs, memory, or custom resources to model-serving workloads.&nbsp;<\/p>\n\n\n\n<ul>\n<li><strong>max_ongoing_requests<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Limits how many requests a replica can handle at once. This helps control latency and prevent a model replica from being overloaded.&nbsp;<\/p>\n\n\n\n<ul>\n<li><strong>serve deploy<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Deploys a Ray Serve application using a YAML config file. This is commonly used for production because it separates deployment settings from Python code.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ray Serve Tutorial: Step-by-Step Guide<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Install Ray Serve<\/h3>\n\n\n\n<p>Create a <a href=\"https:\/\/www.guvi.in\/blog\/how-to-create-virtual-environment-in-python\/\" target=\"_blank\" rel=\"noreferrer noopener\">virtual environment<\/a> first.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>python -m venv rayserve-env\nsource rayserve-env\/bin\/activate\n<\/code><\/pre>\n\n\n\n<p>For Windows:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>rayserve-env\\Scripts\\activate\n<\/code><\/pre>\n\n\n\n<p>Install Ray Serve and required packages.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pip install -U \"ray&#91;serve]\" fastapi requests\n<\/code><\/pre>\n\n\n\n<p>The ray[serve] extra installs Ray Core, dashboard, cluster launcher, and Serve components.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Create a Ray Serve Application<\/h3>\n\n\n\n<p>Create a file named app.py.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from fastapi import FastAPI\nfrom pydantic import BaseModel\nfrom ray import serve\n\napi = FastAPI()\n\n\nclass ReviewRequest(BaseModel):\n    text: str\n\n@serve.deployment(num_replicas=1)\n@serve.ingress(api)\nclass SentimentModel:\n    def __init__(self):\n        self.positive_words = {\"good\", \"great\", \"excellent\", \"love\", \"fast\"}\n\n    @api.get(\"\/\")\n    def health_check(self):\n        return {\"status\": \"running\", \"service\": \"ray-serve\"}\n\n    @api.post(\"\/predict\")\n    def predict(self, request: ReviewRequest):\n        text = request.text.lower()\n        score = sum(word in text for word in self.positive_words)\n\n        label = \"positive\" if score &gt; 0 else \"neutral\"\n\n        return {\n            \"input\": request.text,\n            \"prediction\": label,\n            \"score\": score\n        }\n\napp = SentimentModel.bind()\n<\/code><\/pre>\n\n\n\n<p>The @serve.deployment decorator turns the class into a Ray Serve deployment. Requests are handled by deployment replicas, and these replicas can be scaled independently.<\/p>\n\n\n\n<div style=\"background-color: #099f4e; border: 3px solid #110053; border-radius: 12px; padding: 18px 22px; color: #FFFFFF; font-size: 18px; font-family: Montserrat, Helvetica, sans-serif; line-height: 1.6; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); max-width: 750px;\">\n  <strong style=\"font-size: 22px; color: #FFFFFF;\">\ud83d\udca1 Did You Know?<\/strong> \n  <br \/><br \/> \n  <strong style=\"color: #FFFFFF;\">Ray<\/strong> now has over <strong style=\"color: #FFFFFF;\">39,000 GitHub stars<\/strong> and has been downloaded more than <strong style=\"color: #FFFFFF;\">237 million times<\/strong>. It recently joined the <strong style=\"color: #FFFFFF;\">PyTorch Foundation<\/strong> alongside projects like <strong style=\"color: #FFFFFF;\">vLLM<\/strong> as part of the open-source AI compute stack.\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Run the Application Locally<\/h3>\n\n\n\n<p>Create another file named run.py.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from ray import serve\nfrom app import app\n\nserve.run(app, route_prefix=\"\/sentiment\")\n<\/code><\/pre>\n\n\n\n<p>Run the file.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>python run.py\n<\/code><\/pre>\n\n\n\n<p>The serve.run() method runs a Serve application created through .bind(). It also exposes the app through the route prefix when HTTP routing is enabled.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Test the API<\/h3>\n\n\n\n<p>Open a new terminal and send a test request.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl -X POST \"http:\/\/127.0.0.1:8000\/sentiment\/predict\" \\\n-H \"Content-Type: application\/json\" \\\n-d '{\"text\": \"Ray Serve is fast and great\"}'\n<\/code><\/pre>\n\n\n\n<p>Expected response:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"input\": \"Ray Serve is fast and great\",\n  \"prediction\": \"positive\",\n  \"score\": 2\n}\n<\/code><\/pre>\n\n\n\n<p>You can also test the health endpoint.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl http:\/\/127.0.0.1:8000\/sentiment\/\n<\/code><\/pre>\n\n\n\n<p>Expected response:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"status\": \"running\",\n  \"service\": \"ray-serve\"\n}\n<\/code><\/pre>\n\n\n\n<p><em>Build production-ready machine learning skills with HCL GUVI\u2019s <\/em><a href=\"https:\/\/www.guvi.in\/zen-class\/machine-learning-course\/?utm_source=blog&amp;utm_medium=hyperlink&amp;utm_campaign=ray-serve-tutorial-how-to-deploy-scalable-ml-models-with-rayserve\" target=\"_blank\" rel=\"noreferrer noopener\"><em>Machine Learning Course<\/em><\/a><em>. Learn ML model development, deployment workflows, MLOps basics, and real-world AI applications through structured, hands-on training designed for aspiring machine learning engineers.<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 5: Scale the Deployment<\/h3>\n\n\n\n<p>Update the deployment line in app.py.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@serve.deployment(num_replicas=2)\n<\/code><\/pre>\n\n\n\n<p>This runs two replicas of the deployment. More replicas help the service handle more concurrent requests, especially when model inference takes time.<\/p>\n\n\n\n<p>For production, scaling should usually be managed through a Serve config file instead of changing code manually.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 6: Create a Production Serve Config<\/h3>\n\n\n\n<p>Create a file named serve_config.yaml.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>applications:\n  - name: sentiment_app\n    route_prefix: \/sentiment\n    import_path: app:app\n    deployments:\n      - name: SentimentModel\n        num_replicas: 2\n<\/code><\/pre>\n\n\n\n<p>Start a local Ray cluster.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ray start --head\n<\/code><\/pre>\n\n\n\n<p>Deploy the application.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>serve deploy serve_config.yaml\n<\/code><\/pre>\n\n\n\n<p>Check deployment status.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>serve status\n<\/code><\/pre>\n\n\n\n<p>Ray Serve recommends config files for production because they let teams configure applications, routes, replicas, HTTP options, and deployment parameters in one place.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>Ray Serve makes model deployment easier by combining <a href=\"https:\/\/www.guvi.in\/blog\/guide-to-python-web-development\/\" target=\"_blank\" rel=\"noreferrer noopener\">Python<\/a>-native development with scalable serving infrastructure. A developer can start with a simple deployment, expose it through <a href=\"https:\/\/www.guvi.in\/blog\/deploying-ml-model-as-a-fastapi-microservice\/\" target=\"_blank\" rel=\"noreferrer noopener\">FastAPI<\/a>, test it locally, and later move the same application into a production setup using Serve config files.<\/p>\n\n\n\n<p>For teams building AI applications, Ray Serve is useful because it supports scalable inference, multiple replicas, model composition, and HTTP-based serving without forcing a specific <a href=\"https:\/\/www.guvi.in\/blog\/introduction-to-machine-learning\/\" target=\"_blank\" rel=\"noreferrer noopener\">ML framework<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>FAQs<\/strong><\/h2>\n\n\n<div id=\"rank-math-faq\" class=\"rank-math-block\">\n<div class=\"rank-math-list \">\n<div id=\"faq-question-1783329153883\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>What is Ray Serve used for?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Ray Serve is used to deploy machine learning models, Python functions, and AI pipelines as scalable APIs.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1783329169476\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>Is Ray Serve only for machine learning models?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>No. Ray Serve can serve ML models, FastAPI apps, Python functions, and multi-step inference pipelines.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1783329187256\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>Can Ray Serve run with FastAPI?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Yes. Ray Serve supports FastAPI through @serve.ingress(), which lets developers define clean HTTP routes inside a Serve deployment.<\/p>\n\n<\/div>\n<\/div>\n<\/div>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>Ray Serve is a scalable model serving library built on Ray. It helps developers turn Python functions, machine learning models, and AI pipelines into production-ready APIs. Ray Serve is framework-agnostic, so it can serve models built with PyTorch, TensorFlow, scikit-learn, Hugging Face, or custom Python code. A Ray Serve tutorial is useful when you want [&hellip;]<\/p>\n","protected":false},"author":60,"featured_media":122546,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[294,717],"tags":[],"views":"39","authorinfo":{"name":"Vaishali","url":"https:\/\/www.guvi.in\/blog\/author\/vaishali\/"},"thumbnailURL":"https:\/\/www.guvi.in\/blog\/wp-content\/uploads\/2026\/07\/Ray-Serve-300x116.webp","_links":{"self":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts\/121154"}],"collection":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/users\/60"}],"replies":[{"embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/comments?post=121154"}],"version-history":[{"count":5,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts\/121154\/revisions"}],"predecessor-version":[{"id":122547,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts\/121154\/revisions\/122547"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/media\/122546"}],"wp:attachment":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/media?parent=121154"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/categories?post=121154"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/tags?post=121154"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}