MLOps &
Deployment Reference

Every tool in the modern MLOps stack — from cloud infrastructure and data pipelines through model serving, monitoring, and LLMOps — with complete deployment examples for Django, Flask, and FastAPI.

Cloud Docker · K8s MLflow · W&B FastAPI · Triton Monitoring LLMOps Deployment Guide
Cloud Containers Data Pipelines Versioning Experiment Tracking CI/CD Model Serving Monitoring LLMOps Hardware Deployment Guide

Core Infrastructure & Cloud Providers

Cloud providers supply on-demand compute, object storage, managed databases, and ML-specific services. The choice between providers usually comes down to your team's existing ecosystem, the managed ML platform on offer, and GPU availability. All three hyperscalers provide a free tier or trial credits, making experimentation accessible before committing.

AWS — Amazon Web Services
Market leader · broadest service catalog

SageMaker covers the full ML lifecycle (data labelling, training, hosting). EC2 provides GPU instances (p3, p4, g4dn). Lambda runs serverless inference. S3 stores models and datasets. ECR hosts container images.

SageMakerEC2 GPULambdaEKSS3
Google Cloud Platform
TPU access · AI-first platform

Vertex AI is the managed ML platform with AutoML, custom training, and model registry. Unique access to TPUs (Tensor Processing Units) for high-throughput deep learning. BigQuery ML runs SQL-based models on petabytes.

Vertex AITPUsBigQuery MLCloud Run
Microsoft Azure
Enterprise integration · exclusive OpenAI partner

Azure ML is the managed platform. Preferred by enterprises already in the Microsoft ecosystem (Active Directory, Office 365). Exclusive Azure OpenAI Service grants API access to GPT-4, DALL-E, and Whisper with enterprise SLAs.

Azure MLOpenAI ServiceAKSBlob Storage
CoreWeave
GPU-specialised cloud

Infrastructure purpose-built for GPU workloads. Offers H100 and A100 clusters at competitive cost-per-FLOP compared to hyperscalers. Kubernetes-native API, low network latency between GPU nodes.

H100 / A100Kubernetes-nativeRDMA networking
Lambda Labs
Developer-friendly GPU rental

Straightforward hourly GPU pricing with no complex billing. On-demand A10, A100, H100 instances accessible via SSH or JupyterLab. Popular with researchers who need GPU access without a cloud contract.

Hourly billingSSH / JupyterPersistent storage
Starting point. AWS and GCP both offer $300 free credits for new accounts. For GPU training experiments, Lambda Labs is the most transparent on pricing. Avoid locking into managed ML platforms (SageMaker, Vertex AI) until you understand your team's actual requirements — their abstraction cost adds up.

Containerization & Orchestration

A container packages your application, runtime, libraries, and system dependencies into a single portable image. This eliminates environment-mismatch failures between development, testing, and production. Orchestrators manage running containers at scale across clusters of machines, handling restarts, scaling, and network routing automatically.

Docker
Container runtime · image builder

The universal container standard. A Dockerfile defines the environment reproducibly. Docker Compose manages multi-container applications locally (API + Redis + database). Every ML deployment starts here.

Dockerfiledocker-composeDocker Hub
Kubernetes (K8s)
Container orchestration · production scale

Industry standard for running containers at scale. Handles automatic restart of failed containers, horizontal pod autoscaling, rolling updates with zero downtime, and service discovery. Required knowledge for any production ML platform role.

PodsDeploymentsServicesHPA
K3s
Lightweight Kubernetes

Certified minimal Kubernetes distribution with a ~70MB binary and 512MB RAM footprint instead of 4GB+. Suitable for edge deployments, on-premise servers, and learning Kubernetes without resource overhead.

Edge MLOn-premiseSingle binary
Helm
Kubernetes package manager

Helm Charts are versioned, parameterised templates for Kubernetes resources. Instead of maintaining hundreds of lines of YAML, install a community chart with a single command and override values as needed.

ChartsValues filesReleases

Dockerfile for an ML API

dockerfile
FROM python:3.11-slim

WORKDIR /app

# Copy requirements before source code so Docker caches the pip layer
# and only re-installs when requirements.txt changes
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

# Run as non-root user
RUN adduser --disabled-password --gecos '' appuser
USER appuser

EXPOSE 8000

HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:8000/health || exit 1

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
docker — daily workflow
docker build -t my-ml-api:v1.0 .
docker run -p 8000:8000 my-ml-api:v1.0
docker run -d --name ml-api -p 8000:8000 my-ml-api:v1.0
docker logs ml-api -f
docker exec -it ml-api /bin/bash

docker-compose up -d
docker-compose down

Data Pipeline & Feature Stores

Pipeline orchestrators schedule and execute the data ingestion, transformation, and loading steps that feed ML training. Feature stores ensure that the feature transformations applied during training are applied identically at inference time — eliminating training-serving skew, which is one of the most common causes of production performance degradation.

Apache Airflow
DAG-based workflow orchestrator

Pipelines are defined as Python DAGs (Directed Acyclic Graphs). Rich web UI for monitoring runs, retries, and backfills. 800+ community operators for connecting to databases, cloud storage, and ML services. Battle-tested at Airbnb, Lyft, and major banks.

DAGsSchedulingBackfillWeb UI
Prefect
Python-first orchestration

Decorate any Python function with @flow and @task to make it an orchestrated workflow. Much less boilerplate than Airflow. Prefect Cloud provides managed deployment, scheduling, and observability.

@flow / @taskDeploymentsPrefect Cloud
Dagster
Asset-oriented data platform

Models pipelines as Software-Defined Assets — the datasets, models, and metrics your pipeline produces — rather than tasks. This gives automatic lineage tracking, asset materialisation history, and better testing ergonomics.

AssetsLineageSensorsPartitions
Mage
Notebook-style pipeline builder

Build, test, and run pipelines in a visual notebook interface. Each block (data loader, transformer, exporter) is independently runnable with visible output. Supports streaming, batch, and real-time pipelines.

Visual editorBlocksStreaming
Feast
Open-source feature store

Defines and serves features consistently between training and serving through an offline store (for batch training) and an online store (for low-latency inference). Prevents feature drift by sharing a single definition.

Feature registryPoint-in-time joinsOnline/offline
Tecton
Managed enterprise feature platform

Production-grade managed feature store with sub-10ms online serving, streaming feature pipelines, and monitoring built in. Used by FinTech and e-commerce companies with strict feature SLAs.

Real-time featuresSLA guaranteesMonitoring
Hopsworks
Open-source ML data platform

Combines feature store, model registry, and experiment tracking in one deployable platform. Available on any cloud or on-premise. Strong support for feature groups, time-travel queries, and Great Expectations integration.

Feature storeModel registryOn-premise

Version Control

ML reproducibility requires versioning three distinct artefacts: code (Git), data (DVC or LakeFS), and models (MLflow, DVC, or a model registry). Without all three locked to the same commit, reproducing a specific result — or rolling back a bad model — becomes unreliable.

Git
Source code versioning

The universal distributed version control system. Non-negotiable for any ML project. Branch per experiment, tag releases, use pull requests to review changes to training code and model configs.

BranchingTagsPull requests
GitHub / GitLab / Bitbucket
Remote Git hosting

GitHub has the largest open-source community and GitHub Actions for CI/CD. GitLab offers better built-in CI/CD pipelines and a stronger self-hosted option. Bitbucket integrates with Atlassian (Jira, Confluence) for enterprise teams.

Remote reposCI/CDContainer registry
DVC — Data Version Control
Git for large files and ML pipelines

DVC stores a small pointer file in Git while the actual large file (dataset, model weights) lives in S3, GCS, or Azure Blob. Also defines reproducible ML pipelines as stages with tracked inputs and outputs.

dvc add / push / pullPipelinesRemote storage
Git LFS
Large file storage for Git

Git extension that stores large files outside the repository and replaces them with text pointers. Simpler than DVC, natively supported on GitHub and GitLab. Suitable for models under 2GB without pipeline tracking needs.

git lfs trackGitHub-nativePointer files
LakeFS
Git semantics for data lakes

Provides branches, commits, and merges on top of an existing S3-compatible data lake without copying data. Create a branch to experiment with a new dataset version and merge it only if the model improves.

Data branchesS3-compatibleLineage

DVC commands

dvc workflow
git init && dvc init

# Configure remote storage
dvc remote add -d myremote s3://mybucket/dvc-store

# Track a dataset
dvc add data/train.csv
git add data/train.csv.dvc .gitignore
git commit -m "track training dataset"
dvc push

# On another machine
git clone https://github.com/you/project
dvc pull

Experiment Tracking & Model Registries

Without experiment tracking, the results of 50 training runs live in a Jupyter notebook with no record of which hyperparameter combination produced the best validation score. These tools automatically log parameters, metrics, and artefacts per run and provide a searchable history. Model registries add lifecycle management: staging, production, and archived versions with rollback capability.

MLflow
Open-source · self-hostable

Log metrics and parameters with two lines of code. Built-in model registry, artefact storage, and a local web UI on port 5000. Can be self-hosted on any cloud. The most widely deployed open-source tracking tool.

mlflow.log_metric()Model RegistryREST API
Weights & Biases (W&B)
Managed SaaS · richest feature set

Real-time metric plots, system resource monitoring, artefact versioning, hyperparameter sweep orchestration, and dataset tables. The standard at most serious ML research teams. Free tier covers individual use.

wandb.init()SweepsArtifactsReports
Comet ML
Experiment and production platform

Covers experiment tracking, model production monitoring, and dataset management in a single platform. Strong auto-logging for PyTorch, TF, and scikit-learn with minimal code changes.

Auto-loggingModel monitoringDataset registry
Neptune.ai
Flexible metadata store

Schema-less metadata store that logs anything associated with an ML run — metrics, images, numpy arrays, interactive charts, dataframes. Particularly strong for teams doing image or NLP experiments with rich visualisation needs.

Flexible schemaRich mediaComparison UI
ClearML
Full open-source MLOps platform

Experiment tracking, data management, pipeline orchestration, and model serving in one open-source stack. Self-hostable. Automatic logging requires zero code changes in many frameworks — just add the ClearML agent.

Zero-code loggingPipelinesSelf-hostable

MLflow tracking example

mlflow
import mlflow
import mlflow.sklearn
from sklearn.ensemble        import RandomForestClassifier
from sklearn.datasets        import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics         import accuracy_score

X, y   = load_iris(return_X_y=True)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.2, random_state=42)

mlflow.set_experiment("iris-classification")

with mlflow.start_run():
    n_est, depth = 100, 5
    mlflow.log_param("n_estimators", n_est)
    mlflow.log_param("max_depth",    depth)

    model = RandomForestClassifier(n_estimators=n_est, max_depth=depth)
    model.fit(X_tr, y_tr)
    acc = accuracy_score(y_te, model.predict(X_te))

    mlflow.log_metric("accuracy", acc)
    mlflow.sklearn.log_model(model, "random_forest")

# View runs: mlflow ui  →  http://localhost:5000

CI/CD for Machine Learning

ML CI/CD automates the path from a code commit to a deployed model update. A complete pipeline runs unit tests on data processing code, optionally retrains if training data changed, evaluates the new model against the previous production model, and promotes it only if metrics improve. Failed quality gates block the deployment automatically.

GitHub Actions
The most accessible entry point

Workflows live in .github/workflows/*.yml alongside your code. Triggers on push, pull request, schedule, or custom events. 2000 free minutes/month for public repos. The natural choice if you already host on GitHub.

YAML workflowsMarketplace actionsSecrets
GitLab CI/CD
Built into GitLab

Defined in .gitlab-ci.yml at the repo root. No external service required. Better suited for self-hosted deployments and teams wanting a single platform for Git, CI, and container registry.

.gitlab-ci.ymlRunnersEnvironments
Argo Workflows
Kubernetes-native pipeline engine

Each workflow step runs in its own container on Kubernetes. Ideal for ML pipelines where different stages need different environments — data preprocessing in a Python container, training in a CUDA container, evaluation in another.

K8s-nativeDAG workflowsArtifact passing
Tekton
Cloud-native CI/CD primitives

Kubernetes Custom Resource Definitions for composable Tasks and Pipelines. Lower-level than Argo — you assemble reusable building blocks. Foundation of Red Hat OpenShift Pipelines. Suited for teams wanting maximum control.

TasksPipelinesTekton Hub
CML — Continuous Machine Learning
ML reports in pull requests

By iterative.ai (the DVC team). Posts model metrics, comparison tables, and plots as comments directly on a GitHub or GitLab pull request. Reviewers see the metric delta before approving a merge.

cml commentMetric reportsDVC integration

Model Deployment & Serving

Model serving exposes a trained model's inference function over a network. The requirements span a wide range — a Flask wrapper on a single VM for low-traffic internal tools, to a multi-GPU Triton cluster processing thousands of requests per second. The right choice depends on throughput requirements, hardware, latency budget, and operational complexity tolerance.

FastAPI
Python REST API standard

Async-native, auto-generates OpenAPI documentation at /docs, and uses Pydantic for request/response validation. The default choice for a new standalone ML API. Full example in the Deployment Guide section.

AsyncPydanticAuto docsUvicorn
NVIDIA Triton Inference Server
High-throughput GPU inference

Serves PyTorch, TF, ONNX, and TensorRT models from a single server. Dynamic batching groups concurrent requests into GPU-optimal batch sizes automatically, maximising utilisation. REST and gRPC endpoints.

Dynamic batchingMulti-modelgRPC + REST
TorchServe
Official PyTorch serving

Developed by AWS and Meta for PyTorch models. Packages a model into a .mar archive and serves it with built-in batching, model versioning, A/B testing, and a management REST API.

.mar archivesManagement APIA/B testing
TF Serving
Official TensorFlow serving

Production server for TensorFlow SavedModels. Point it at a versioned directory structure and it automatically discovers and serves new model versions with zero downtime. Runs on CPU or GPU.

SavedModelAuto versioninggRPC
BentoML
Framework-agnostic model packaging

Packages any model — sklearn, PyTorch, XGBoost, or custom — into a self-contained Bento with its inference API and dependencies. One command deploys to Docker, Kubernetes, Lambda, or the managed BentoCloud.

RunnersAdaptive batchingBentoCloud
Seldon Core / KServe
ML on Kubernetes

Kubernetes operators that serve ML models via a custom resource definition — declare your model in YAML, the operator manages the container and scaling. KServe is the newer iteration and supports canary rollouts natively.

InferenceService CRDCanary rolloutsPipeline graphs
vLLM
LLM inference engine

Uses PagedAttention to manage KV-cache GPU memory efficiently. Delivers 10–20× higher throughput than naive HuggingFace generation. Exposes an OpenAI-compatible REST API. The production standard for self-hosted LLMs.

PagedAttentionContinuous batchingOpenAI-compatible
Ollama
Local LLM runner

ollama run llama3 downloads and runs an open-source LLM locally. Serves an OpenAI-compatible REST endpoint. Best for local development, prompt iteration, and private inference without cloud costs.

Local inferenceModelfileOpenAI-compatible
TGI — Text Generation Inference
Hugging Face production LLM server

Hugging Face's inference server for HF Hub models. Flash Attention 2, continuous batching, quantisation (GPTQ, AWQ, bitsandbytes), and streaming via Server-Sent Events. Deploys any supported model with one Docker command.

Flash Attention 2GPTQ / AWQSSE streaming

Model Monitoring & Observability

Models degrade silently. Data drift (the input distribution shifts), concept drift (the relationship between inputs and outputs changes), and upstream data quality issues all cause prediction quality to erode over time. Monitoring catches these problems before they produce material business impact.

Prometheus
Metrics collection and alerting

Time-series metrics database that scrapes a /metrics HTTP endpoint on your API at regular intervals. Stores request latency, error rates, prediction counts, and custom ML metrics. Pairs with Alertmanager for notification routing.

PromQLScrapingAlertmanager
Grafana
Dashboards and visualisation

Connects to Prometheus, InfluxDB, Elasticsearch, and 50+ other sources to render live dashboards. Set threshold alerts to fire on Slack, PagerDuty, or email when a metric crosses a boundary.

DashboardsAlertingMulti-source
Evidently AI
ML-specific monitoring reports

Open-source library that generates interactive HTML reports and JSON metrics comparing the current data distribution to a reference baseline. Can run as a standalone monitoring service with scheduled checks and a UI.

Data driftTarget driftTest suites
Arize AI
Enterprise ML observability

Managed observability platform. Log predictions and ground truth labels; Arize tracks performance, data quality, and drift over time with UMAP embedding visualisation for diagnosing NLP and vision model failures.

Embedding monitoringSHAPLLM tracing
WhyLogs / WhyLabs
Lightweight statistical profiles

WhyLogs generates statistical sketches (distributions, null rates, cardinality) of data without storing the raw data itself — making it suitable for high-volume or sensitive data. WhyLabs is the managed monitoring dashboard.

Data sketchingLow overheadStreaming
LangSmith
LLM tracing and evaluation

LangChain's observability platform. Traces every step in an LLM chain with prompt content, token usage, latency, and cost. Supports human annotation, automatic evaluation datasets, and prompt version management.

LLM tracingPrompt versioningEvals
Phoenix (Arize)
Open-source LLM observability

Open-source local observability tool from the Arize team. Runs entirely in your environment — no data leaves your machine. Traces LLM calls, visualises embeddings, and evaluates retrieval quality for RAG pipelines.

Local tracingEmbedding vizRAG eval

LLMOps & GenAI Orchestration

LLMOps covers the tooling layer built specifically for large language model applications — chaining LLM calls, retrieving relevant context (RAG), routing queries to tools or agents, and evaluating output quality. These tools emerged from 2022 onward and are maturing rapidly.

LangChain
LLM application framework

Chains, agents, tools, and memory abstractions for building LLM applications. Supports 50+ LLM providers and 100+ vector databases. Most popular starting point for RAG systems and multi-step agent workflows.

ChainsAgentsRAGMemory
LlamaIndex
Data framework for LLMs

Specialises in connecting LLMs to structured and unstructured data sources. Best-in-class RAG: ingest PDFs, databases, APIs into a vector store and query them with natural language. Stronger than LangChain for complex retrieval tasks.

Document loadersQuery enginesSub-question decomposition
Haystack
Production NLP pipelines

deepset's framework for search, question answering, and RAG systems. More structured API than LangChain — better suited for production NLP products requiring strong document store abstractions and evaluation pipelines.

Document storesPipelinesEvaluation
Flowise
Visual LLM flow builder

Drag-and-drop UI for building LangChain flows without writing code. Connect LLM nodes, retrievers, memory, and tool nodes visually. Exports flows to a deployable REST API. Useful for rapid prototyping with non-technical stakeholders.

No-codeREST exportEmbedded chat
Langfuse
Open-source LLM engineering platform

Traces LLM calls with prompt content, token cost, and latency. Manages prompt versions with a registry, collects user feedback, and runs evaluation datasets. Self-hostable open-source alternative to LangSmith.

TracingPrompt registrySelf-hostable

Hardware Acceleration & Runtime Optimisation

Training and inference performance depends heavily on hardware-specific optimisations. Compiling a model for a target runtime — TensorRT for NVIDIA GPUs, ONNX Runtime for CPU, OpenVINO for Intel — can reduce inference latency by 2–5× without changing the model architecture.

NVIDIA CUDA / cuDNN
GPU compute foundation

CUDA is the parallel computing platform that allows Python code to execute on NVIDIA GPUs. cuDNN provides hand-optimised implementations of convolutions, attention, and activation functions. Both install automatically with PyTorch GPU builds.

GPU parallelismtorch.cudaMixed precision
TensorRT
NVIDIA inference optimiser

Takes a trained model and applies layer fusion, FP16/INT8 quantisation, and kernel auto-tuning to produce an engine optimised for a specific NVIDIA GPU. Typically delivers 3–5× lower latency compared to PyTorch eager mode inference.

FP16 / INT8Layer fusionKernel tuning
ONNX / ONNX Runtime
Cross-framework interchange format

Export a model from PyTorch or TensorFlow to ONNX once; run it on any hardware via ONNX Runtime. ORT's CPU execution provider consistently outperforms PyTorch on CPU-only inference tasks and supports dynamic batch sizes.

Cross-frameworkCPU optimisedMobile / edge
Hugging Face Optimum
Transformers on any hardware

One-line export of HF Transformers models to ONNX, TensorRT, or Intel OpenVINO. Handles graph optimisation and quantisation. Designed so switching inference backend requires minimal code changes.

ONNX exportQuantisationMulti-backend
OpenVINO
Intel hardware optimisation

Intel's toolkit for deploying deep learning on Intel CPUs, integrated GPUs, VPUs, and FPGAs. Relevant when deploying on Intel-based edge devices or on-premise servers where NVIDIA GPUs are absent. INT8 quantisation gives 2–5× CPU inference speedup.

Intel CPU/GPU/VPUINT8 quantEdge

PyTorch to ONNX Runtime

pytorch → onnx → ort
import torch
import onnxruntime as ort
import numpy as np

model.eval()
dummy = torch.randn(1, 10)

torch.onnx.export(
    model, dummy, "model.onnx",
    input_names    = ["features"],
    output_names   = ["output"],
    dynamic_axes   = {"features": {0: "batch_size"}}
)

session = ort.InferenceSession("model.onnx")
x       = np.random.randn(5, 10).astype(np.float32)
outputs = session.run(None, {"features": x})
print(outputs[0])

Deployment Guide

Three frameworks for exposing a trained model as a web API. The pattern is identical in all three: load the model once when the process starts, accept serialised input over HTTP, run inference, and return a JSON response. The differences are in how much surrounding infrastructure each framework provides and the async model they use.

FastAPI

  • Async by default — handles concurrent requests without blocking
  • Auto-generates /docs Swagger UI
  • Pydantic validates every request and response
  • Best choice for new standalone ML APIs

Flask

  • Synchronous — run with Gunicorn for production
  • Minimal boilerplate, large extension ecosystem
  • Good for adding ML to an existing Flask application
  • Simpler mental model for smaller teams

Django

  • Full ORM, admin interface, and auth built in
  • Use Django REST Framework for the API layer
  • Higher overhead than Flask/FastAPI
  • Right choice when ML is a feature inside a larger web product

FastAPI

fastapi ml api
"""
Run: uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
"""
from fastapi            import FastAPI, HTTPException
from pydantic           import BaseModel, Field
from contextlib         import asynccontextmanager
import joblib, numpy as np, logging

logger = logging.getLogger(__name__)
model  = None

@asynccontextmanager
async def lifespan(app: FastAPI):
    global model
    model = joblib.load("model.pkl")   # loaded once at startup, shared across all requests
    logger.info("Model loaded")
    yield

app = FastAPI(title="ML API", version="1.0.0", lifespan=lifespan)

class PredictInput(BaseModel):
    features: list[float] = Field(..., min_length=1)

    model_config = {"json_schema_extra": {"example": {"features": [1.2, 0.5, 3.1]}}}

class PredictOutput(BaseModel):
    prediction: float

@app.get("/health")
def health():
    return {"status": "ok", "model_loaded": model is not None}

@app.post("/predict", response_model=PredictOutput)
def predict(req: PredictInput):
    if model is None:
        raise HTTPException(503, "Model not available")
    try:
        x    = np.array(req.features).reshape(1, -1)
        pred = float(model.predict(x)[0])
        return PredictOutput(prediction=pred)
    except Exception as e:
        logger.error(e)
        raise HTTPException(500, "Inference failed")

@app.post("/predict/batch")
def predict_batch(inputs: list[PredictInput]):
    x    = np.array([r.features for r in inputs])
    preds = model.predict(x).tolist()
    return {"predictions": preds, "count": len(preds)}

Flask

flask ml api
"""
Production: gunicorn -w 4 -b 0.0.0.0:5000 app:app
Dev:        python app.py
"""
from flask import Flask, request, jsonify, abort
import joblib, numpy as np, logging

app = Flask(__name__)
logging.basicConfig(level=logging.INFO)

try:
    model = joblib.load("model.pkl")
except FileNotFoundError:
    model = None
    app.logger.error("model.pkl not found")

@app.route("/health")
def health():
    return jsonify({"status": "ok", "model_loaded": model is not None})

@app.route("/predict", methods=["POST"])
def predict():
    if model is None:
        abort(503, "Model not loaded")
    data = request.get_json()
    if not data or "features" not in data:
        abort(400, "'features' key required")
    try:
        x    = np.array(data["features"]).reshape(1, -1)
        pred = float(model.predict(x)[0])
        prob = model.predict_proba(x)[0].tolist() if hasattr(model, "predict_proba") else None
        return jsonify({"prediction": pred, "probability": prob})
    except Exception as e:
        app.logger.error(e)
        abort(500, "Inference failed")

@app.errorhandler(400); @app.errorhandler(500); @app.errorhandler(503)
def handle_error(e):
    return jsonify({"error": str(e.description)}), e.code

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=False)

Django with Django REST Framework

django + drf
# pip install django djangorestframework joblib
# Add 'rest_framework' to INSTALLED_APPS

# apps/predictor/apps.py
from django.apps import AppConfig
import joblib, logging, os

logger = logging.getLogger(__name__)

class PredictorConfig(AppConfig):
    name  = "predictor"
    model = None

    def ready(self):
        path = os.path.join(os.path.dirname(__file__), "model.pkl")
        try:
            PredictorConfig.model = joblib.load(path)
            logger.info("Model loaded")
        except Exception as e:
            logger.error(f"Load failed: {e}")

# apps/predictor/serializers.py
from rest_framework import serializers

class InputSerializer(serializers.Serializer):
    features = serializers.ListField(child=serializers.FloatField(), min_length=1)

# apps/predictor/views.py
from rest_framework.views    import APIView
from rest_framework.response import Response
from rest_framework          import status
import numpy as np
from .serializers import InputSerializer
from .apps        import PredictorConfig

class PredictView(APIView):
    def post(self, request):
        s = InputSerializer(data=request.data)
        if not s.is_valid():
            return Response(s.errors, status=status.HTTP_400_BAD_REQUEST)
        m = PredictorConfig.model
        if m is None:
            return Response({"error": "Model unavailable"}, status=503)
        x    = np.array(s.validated_data["features"]).reshape(1, -1)
        pred = float(m.predict(x)[0])
        return Response({"prediction": pred})

# apps/predictor/urls.py
from django.urls import path
from .views import PredictView
urlpatterns = [path("predict/", PredictView.as_view())]

Deploying the containerised API

deployment targets
# Render — connect GitHub repo, auto-detects Dockerfile, zero config

# AWS ECR + ECS
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin 123456789.dkr.ecr.us-east-1.amazonaws.com
docker build -t my-ml-api .
docker tag  my-ml-api:latest 123456789.dkr.ecr.us-east-1.amazonaws.com/my-ml-api:latest
docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/my-ml-api:latest

# Kubernetes deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ml-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: ml-api
  template:
    metadata:
      labels:
        app: ml-api
    spec:
      containers:
      - name: ml-api
        image: your-registry/my-ml-api:latest
        ports:
        - containerPort: 8000
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 10
Production checklist. Load the model at process startup, not per request. Run Gunicorn or Uvicorn workers — never the development server. Always expose a /health endpoint. Log every prediction with a unique ID. Monitor the first 1000 production predictions before trusting automated alerting thresholds.