Practical MLOps · Serving and inference layer

Production ML Model Serving: FastAPI, Ray Serve, Triton or KServe

The controlled path from a versioned model artifact to a measurable online or batch service. The right runtime depends on latency, throughput, batching, hardware, rollout, and operational ownership — not on which tool is most popular.

Documented from official sources

Direct answer

Production model serving is the controlled path from a versioned model artifact to a measurable online or batch service. FastAPI is useful for a thin application API, Ray Serve for Python-native composition and scaling, Triton for optimized multi-framework inference, and KServe for Kubernetes-native serving workflows. The right choice depends on latency, throughput, batching, hardware, rollout, and operational ownership.

Serving architecture and artifact-to-runtime contract

  1. GatewayTLS, auth, rate limiting
  2. ValidationSchema check, payload size
  3. PreprocessingNormalize, tokenize, resize
  4. InferenceModel forward pass (batched)
  5. PostprocessingDecode, threshold, format
  6. Response & TelemetryReturn result; export latency, error, count

Every serving runtime implements this path. The difference is how much of it the runtime handles for you and how much you build.

Artifact-to-runtime contract

Inputs

  • Model artifact from MLflow registry (via @champion alias)
  • Container image with runtime and dependencies
  • Serving configuration (replicas, batching, resources)
  • Input schema (model signature)

Outputs

  • Predictions via HTTP or gRPC
  • Operational telemetry (latency, error rate, throughput)
  • Health and readiness signals

State owned

  • Loaded model instances in memory
  • Request queue and batching state
  • Replica count and autoscaling state

Failure boundary

The serving runtime does not own model quality, data quality, or the decision to promote. It serves what the registry points to and reports what it observes. If the model is wrong, the runtime serves wrong answers quickly and reliably.

Choosing a production model-serving runtime

No runtime is best. Make the decision falsifiable through workload requirements.

FastAPI

Choose when
You need a thin application API around a model, you are comfortable building batching and scaling yourself, and your model is a Python object that loads in-process.
Avoid when
You need dynamic batching, multi-GPU inference, Kubernetes-native autoscaling, or production-grade fault recovery without building it.
Operational tradeoff
Maximum flexibility and minimal abstraction. You own everything: batching, scaling, health checks, reload behavior. Fast to prototype, expensive to harden.

Ray Serve

Choose when
You want Python-native composition (multiple models, pre/post-processing as separate deployments), need scaling and fault tolerance, and your team is Python-first.
Avoid when
You need maximum GPU inference throughput for multi-framework models, or your team prefers Kubernetes-native configuration over Python deployment configs.
Operational tradeoff
Composable Python-native serving with built-in scaling and fault tolerance. Production deployment via KubeRay RayService CR on Kubernetes. Less optimized for raw GPU throughput than Triton.

NVIDIA Triton Inference Server

Choose when
You need optimized multi-framework inference (TensorFlow, PyTorch, ONNX, TensorRT), dynamic batching, concurrent model instances on GPUs, and you have GPU hardware.
Avoid when
You are serving on CPU only, your model is a simple Python object, or you do not need GPU-level throughput optimization.
Operational tradeoff
Highest inference throughput with dynamic batching and instance groups. Configured via config.pbtxt, not Python code. Requires GPU hardware and NVIDIA container infrastructure.

KServe

Choose when
You want Kubernetes-native serving with a standard CRD (InferenceService), canary rollouts, A/B testing, scale-to-zero, and multi-framework support without managing individual deployments.
Avoid when
You are not on Kubernetes, or you need fine-grained control over batching and GPU instance groups that KServe's abstraction does not expose.
Operational tradeoff
Kubernetes-native abstraction over serving infrastructure. Canary rollout via canaryTrafficPercent is only supported in serverless (Knative) deployment mode. Scale-to-zero and KPA autoscaling require Knative deployment. Standard Kubernetes deployment provides full resource control but does not automatically provide canary rollout or scale-to-zero. Choose the deployment mode based on your workload requirements.

TorchServe (maintenance-status-aware)

Choose when
Current official repository evidence supports its active maintenance and you need PyTorch-specific serving with torchserve conventions.
Avoid when
The repository shows maintenance concerns, or you need multi-framework support.
Operational tradeoff
PyTorch-native, but check the official GitHub repository for current maintenance status before selecting. KServe and Ray Serve both support PyTorch models with broader ecosystems.

Online, asynchronous, streaming, and batch serving boundaries

Online serving returns a prediction synchronously within a latency budget (milliseconds to seconds). The client waits. This is the default for user-facing applications.

Asynchronous serving accepts a request and returns a job ID; the client polls or receives a callback when the result is ready. Use this when inference takes longer than a synchronous timeout (large models, batch processing within a request).

Streaming serving returns results incrementally — token by token for LLMs, or frame by frame for video. The connection stays open and results flow as they are produced.

Batch serving processes a dataset offline and writes results to storage. There is no online client. Use this for recurring scoring jobs, backfills, and reports. Batch serving does not need a serving runtime — it can be a pipeline step.

Dynamic batching, concurrency, and backpressure

Dynamic batching combines multiple inference requests into a single batch to maximize throughput. NVIDIA Triton enables it via config.pbtxt with dynamic_batching { }. The max_queue_delay_microseconds setting controls how long the scheduler waits to collect more requests before launching the batch.

Concurrent model execution uses instance_group in Triton's config to spawn multiple model instances on the same or different GPUs. This is useful when a single instance cannot saturate the GPU or when models in an ensemble have different throughputs.

Backpressure is the signal that the serving runtime is at capacity. A growing request queue, rising p95 latency, or rejected connections are backpressure signals. The response is to scale replicas, enable or tune dynamic batching, or shed load. Ignoring backpressure leads to OOM and cascading failures.

  • Dynamic batching: Triton config.pbtxt → dynamic_batching { }
  • Queue delay: max_queue_delay_microseconds controls batch collection window
  • Instance groups: instance_group [{ count: N, kind: KIND_GPU, gpus: [0, 1] }]
  • Backpressure signals: queue growth, p95 rise, connection rejection
  • Backpressure response: scale replicas, tune batching, shed load

Health checks, autoscaling and cold starts

Autoscaling should be driven by the signal that matters to users: latency. Scaling on CPU alone misses GPU-bound workloads where CPU is idle but inference is saturated. Scale on p95 latency, queue depth, or request rate — whichever reflects the bottleneck.

Cold-start is the latency of a new replica loading the model. For large models (GBs), cold-start can be minutes. Scale early enough that a traffic spike does not wait for cold-starts, or keep warm replicas above the minimum.

KServe supports scale-to-zero for predictive workloads, which saves cost but introduces cold-start on the first request. Use scale-to-zero for low-traffic models where cold-start is acceptable, not for latency-critical user-facing endpoints.

Health checks, autoscaling and cold starts

Readiness means the model is loaded and the runtime can accept requests. A readiness check failing removes the replica from the load balancer without killing it. Liveness means the process is healthy; a liveness check failing restarts the pod.

Dependency health checks cover downstream services the runtime depends on: the model registry, the feature store, the monitoring backend. If a dependency is down, the runtime should report not-ready rather than serving errors.

Timeouts and retries should be set on the client side and the runtime side. A client timeout longer than the runtime's latency budget wastes resources. A retry without backpressure amplifies load during an incident. Use circuit breakers to stop sending traffic to a failing downstream rather than retrying indefinitely.

Canary, shadow, blue/green, and rollback patterns

Canary release routes a small percentage of traffic to the new model version while the rest stays on the current version. If the canary's metrics (error rate, latency, business outcome) regress, traffic is rolled back. KServe supports canary rollouts via the canaryTrafficPercent field in the InferenceService spec, but only in serverless (Knative) deployment mode. Standard Kubernetes deployment does not provide this capability.

Shadow release sends the same traffic to both versions but only returns the current version's response. The new version's predictions are logged and compared offline. This tests the new model without user impact.

Blue/green deployment runs two full environments (blue = current, green = new). Traffic is switched from blue to green atomically. If the green environment fails, traffic switches back to blue. This requires double the resources during the switch.

Rollback means redirecting traffic back to the previous version. With MLflow aliases, this can be alias reassignment (@champion back to the previous version). With KServe, it is reverting the canary split. The rollback path must be tested before you need it.

Benchmark methodology and serving failures

Benchmark numbers are not published on this page. When benchmarks are run, they must include the following to be credible:

  • Exact hardware (GPU model, CPU, memory, network)
  • Software versions (runtime, model framework, CUDA)
  • Model and input shape (e.g. ResNet-50, 224x224x3, batch 8)
  • Warm-up period before measurement
  • Concurrency range tested (e.g. 2 to 16 concurrent requests)
  • p50, p95, p99 latency
  • Throughput (inferences per second)
  • Error rate
  • Batch configuration (dynamic batching on/off, max batch size)
  • Measurement tool (e.g. Triton Performance Analyzer, wrk, locust)
  • Date and code commit

How serving fails and recovers

FailureObservable signalLikely causeFirst diagnosticContainmentDurable fixEvidence
Schema mismatch on inputRuntime returns 400 Bad Request; preprocessing error in logsClient sent different schema than model signature; model retrained with new featuresCompare request schema against MLflow model signatureReject the request with a clear error messageVersion the model signature; validate at gateway before forwarding to runtimeEngineering inference from serving best practices
Out of memory (OOM)Replica killed by OOM killer; restart loopModel too large for replica memory, or batch size exceeds memoryCheck memory usage and batch size configurationReduce batch size or increase replica memorySet memory limits with headroom; add OOM alerting; profile model memoryEngineering inference from Kubernetes and serving documentation
Saturation under loadp95 latency rises; throughput plateausReplicas at capacity; queue growingCheck Prometheus for queue depth, replica count, GPU utilizationScale replicas or enable dynamic batchingSet autoscaling on p95 latency, not just CPU; tune batching configurationDocumented from NVIDIA Triton and Ray Serve documentation
Queue growth without processingRequest queue grows; requests time outAll replicas unhealthy or stuck on a slow requestCheck replica health and recent request tracesRestart unhealthy replicas; shed loadAdd circuit breaker; set queue depth limits and rejection thresholdsEngineering inference from serving best practices
Dependency timeoutRequests fail with dependency error; latency spikesFeature store, model registry, or downstream service is slow or downCheck dependency health from the runtime's perspectiveFail fast with a clear error; use cached features if availableAdd circuit breakers for dependencies; set per-dependency timeoutsEngineering inference from serving best practices
Bad model loadReplica fails readiness check; model file error in logsArtifact corrupted, wrong format, or version incompatibilityCheck model artifact URI and format against runtime expectationsRoll back to previous @champion versionAdd a model load test to CI before promotionEngineering inference from MLflow and serving documentation
Canary regressionCanary's error rate or latency worse than baselineNew model version performs worse on real traffic than in evaluationCompare canary vs baseline metrics in GrafanaRoll back canary to 0% trafficRequire canary observation period and automatic rollback thresholds before full promotionDocumented from KServe canary rollout documentation
Telemetry lossNo metrics appearing in Grafana for a runtimeMetrics exporter down, scraping misconfigured, or network policy blockingCheck Prometheus targets and exporter healthFix exporter; use access logs as temporary fallbackAlert on metric absence; test scraping in stagingEngineering inference from Prometheus best practices

Tested environment and limitations

Tool versions

  • NVIDIA Triton: documented (config.pbtxt, dynamic batching)
  • Ray Serve: 2.43+ (production guide documented)
  • KServe: v0.15+ (InferenceService CRD documented)
  • Triton Performance Analyzer: 23.10 (archived docs)
Date verified:

Known limitations

  • No benchmark numbers are published on this page. Benchmark results will be published only after measurement in a documented environment with the methodology listed above.
  • TorchServe maintenance status should be verified against the official GitHub repository (github.com/pytorch/serve) before selection.
  • Triton Performance Analyzer documentation referenced is from archive version 23.10. Verify current version documentation for the latest measurement options.

Sources

The SourceLedger makes technical claims auditable and gives search and retrieval systems explicit source context. It does not guarantee citation, ranking or inclusion.

  1. 01Tier 1NVIDIA

    NVIDIA Triton — Dynamic Batching & Concurrent Model Execution

    Paraphrased. Dynamic batching improves both latency and throughput for stateless models.

    Supports claims:

    • dynamic batching combines inference requests into a single batch
    • configured via config.pbtxt: dynamic_batching { }
    • max_queue_delay_microseconds for batch collection delay
    • instance_group for concurrent model execution on GPUs
    • Performance Analyzer for benchmarking
    • stateless models for dynamic batching; sequence batcher for stateful

    Last verified:

    https://docs.nvidia.com/deeplearning/triton-inference-server/user-guide/docs/tutorials/Conceptual_Guide/Part_2-improving_resource_utilization/README.html
  2. 02Tier 1NVIDIA

    NVIDIA Triton — Model Configuration

    Paraphrased from official documentation.

    Supports claims:

    • model configuration via config.pbtxt
    • instance_group, dynamic_batching, priority configuration

    Last verified:

    https://docs.nvidia.com/deeplearning/triton-inference-server/user-guide/docs/user_guide/model_configuration.html
  3. 03Tier 1NVIDIA

    NVIDIA Triton — Performance Analyzer

    Version: Triton 23.10

    Archived version documentation. Used for benchmark methodology reference.

    Supports claims:

    • Performance Analyzer tool for measuring Triton serving performance
    • concurrency-range, percentile, throughput, latency measurement

    Last verified:

    https://docs.nvidia.com/deeplearning/triton-inference-server/archives/triton-inference-server-2310/user-guide/docs/user_guide/perf_analyzer.html
  4. 04Tier 1Ray

    Ray Serve — Production Guide

    Version: Ray 2.43+

    RayService custom resource automatically handles production requirements.

    Supports claims:

    • production deployment via KubeRay RayService CR on Kubernetes
    • serve build / serve deploy / serve status workflow
    • config file as single source of truth for deployment
    • health checking, status reporting, failure recovery, upgrades handled by RayService
    • deploy on VMs as alternative to Kubernetes

    Last verified:

    https://docs.ray.io/en/latest/serve/production-guide/index.html
  5. 05Tier 1Ray

    Ray Serve — Fault Tolerance

    Paraphrased from official documentation.

    Supports claims:

    • Serve deployment fault tolerance and recovery
    • replica failure handling

    Last verified:

    https://docs.ray.io/en/latest/serve/production-guide/fault-tolerance.html
  6. 06Tier 1KServe

    KServe Documentation

    Version: KServe v0.20

    Paraphrased. Canary rollout, scale-to-zero, and KPA autoscaling are deployment-mode dependent — see kserve-canary, kserve-kpa-autoscaler, and kserve-admin-guide sources. Do not present these as universal KServe behavior.

    Supports claims:

    • KServe as Kubernetes CRD for serving ML models (InferenceService)
    • multi-framework support (TensorFlow, PyTorch, scikit-learn, XGBoost, ONNX)
    • control plane: model revision tracking
    • data plane: standardized inference protocol
    • KServe joined CNCF as incubating project (November 2025)

    Last verified:

    https://kserve.github.io/website/
  7. 07Tier 1PyTorch / GitHub

    TorchServe Repository

    Check repository for current maintenance status before recommending. Include only if current official evidence supports it.

    Supports claims:

    • TorchServe repository and current maintenance status

    Last verified:

    https://github.com/pytorch/serve
  8. 08Tier 1MLflow

    MLflow Model Registry

    Version: MLflow 3.x

    Aliases are mutable named references to model versions, useful for deployment promotion. OSS registry provides UI + API; Databricks extends with Unity Catalog.

    Supports claims:

    • model registration and versioning
    • model aliases (e.g. @champion)
    • model lifecycle: staging, production
    • tags for governance
    • lineage to MLflow runs
    • Databricks Unity Catalog integration for governance

    Last verified:

    https://mlflow.org/docs/latest/ml/model-registry/
  9. 09Tier 1KServe

    KServe Canary Rollout Strategy

    Version: KServe v0.18+

    Paraphrased. Official documentation states: 'Canary rollout strategy is only supported in serverless deployment mode.' Standard Kubernetes deployment does not provide canary rollout via canaryTrafficPercent.

    Supports claims:

    • canary rollout via canaryTrafficPercent field
    • canary rollout is ONLY supported in serverless (Knative) deployment mode
    • KServe tracks last good revision for automatic rollback
    • bad revisions do not receive traffic
    • rollback pins 100% traffic to previous good revision

    Last verified:

    https://kserve.github.io/website/docs/0.18/model-serving/predictive-inference/rollout-strategies/canary
  10. 10Tier 1KServe

    KServe Autoscaling with Knative Pod Autoscaler

    Version: KServe v0.20

    Paraphrased. KPA autoscaler is NOT available in standard Kubernetes deployment mode. Scale-to-zero is a Knative/serverless feature, not a universal KServe capability.

    Supports claims:

    • KPA (Knative Pod Autoscaler) is only supported in Knative deployment mode
    • scale-to-zero requires minReplicas: 0 and Knative/serverless deployment
    • autoscaling metrics: concurrency, rps, cpu, memory
    • cold-start cost when pods scale from zero
    • containerConcurrency as a hard limit on simultaneous requests
    • 60-second stable window and 6-second panic window for autoscaling

    Last verified:

    https://kserve.github.io/website/docs/model-serving/predictive-inference/autoscaling/kpa-autoscaler
  11. 11Tier 1KServe

    KServe Administrator Guide — Deployment Modes

    Version: KServe v0.20

    Paraphrased. Deployment mode determines available features. Standard Kubernetes deployment does NOT automatically provide scale-to-zero, KPA autoscaling, or canary rollout.

    Supports claims:

    • three deployment modes: Standard Kubernetes, Knative/Serverless, LLMInferenceService
    • Standard deployment: full resource control, GPU workloads, production
    • Knative/Serverless deployment: scale-to-zero, burst/unpredictable traffic
    • LLMInferenceService: advanced LLM features (prefix routing, disaggregated serving)
    • InferenceService (Standard) works for all workloads
    • Gateway API recommended for generative inference streaming

    Last verified:

    https://kserve.github.io/website/docs/admin-guide/overview

Deploy, measure and troubleshoot the serving path

Move from a comparison table to a working service with health checks, load testing, observability and a tested rollback path.

  • Deploy a versioned model service.
  • Measure latency, throughput and errors.
  • Diagnose saturation and deployment failures.
Build the serving workflow in the live program