TensorFlow Serving with REST API

TensorFlow Serving is a production-grade server that loads SavedModels and exposes them as REST and gRPC endpoints. Any application — a web backend, a mobile app server, a data pipeline — can send HTTP requests and receive predictions without running Python or knowing anything about TensorFlow. TF Serving handles model versioning, hardware acceleration, request batching, and zero-downtime model swaps automatically.

Why Use TF Serving Instead of Flask or FastAPI

Flask/FastAPI approach:
  You write:
    - Python prediction code
    - Request parsing
    - Response formatting
    - Error handling
    - Batching logic
    - GPU management
  Problems: Not optimized for ML, hard to scale, manual batching

TF Serving approach:
  You provide:
    - SavedModel directory
  TF Serving handles everything else:
    - REST and gRPC endpoints automatically
    - Request batching (combines simultaneous requests)
    - GPU inference acceleration
    - Multiple model versions
    - Health checks
    - Monitoring metrics

Step 1 — Export the Model in TF Serving Layout

import tensorflow as tf
import os

# TF Serving expects: model_name/version_number/
model_name = 'image_classifier'
version    = 1
export_dir = f'serving_models/{model_name}/{version}'

model.save(export_dir)
print(f"Model saved to: {export_dir}")

# Resulting structure:
# serving_models/
# └── image_classifier/
#     └── 1/
#         ├── saved_model.pb
#         └── variables/

Step 2 — Start TF Serving With Docker

# Pull the TF Serving Docker image
docker pull tensorflow/serving

# Start the server
docker run -d --name tf_serving \
  -p 8501:8501 \
  --mount type=bind,\
source=$(pwd)/serving_models/image_classifier,\
target=/models/image_classifier \
  -e MODEL_NAME=image_classifier \
  tensorflow/serving

# The server is now running at:
# REST API:  http://localhost:8501/v1/models/image_classifier
# gRPC API:  localhost:8500

Step 3 — Check Server Health

import requests

# Check model status
response = requests.get(
    'http://localhost:8501/v1/models/image_classifier'
)
print(response.json())

# Expected output:
# {
#   "model_version_status": [{
#     "version": "1",
#     "state": "AVAILABLE",
#     "status": {"error_code": "OK"}
#   }]
# }

Step 4 — Send a Prediction Request

import requests
import json
import numpy as np

# Prepare input data
sample_image = np.random.random((1, 224, 224, 3)).astype('float32')

# TF Serving REST format: {"instances": [list_of_inputs]}
payload = json.dumps({
    'instances': sample_image.tolist()
})

# Send POST request to the predict endpoint
response = requests.post(
    'http://localhost:8501/v1/models/image_classifier:predict',
    data=payload,
    headers={'Content-Type': 'application/json'}
)

# Parse the response
result = response.json()
predictions = result['predictions']
print(f"Prediction shape: {np.array(predictions).shape}")
# (1, 10) — 10 class probabilities
predicted_class = np.argmax(predictions[0])
print(f"Predicted class: {predicted_class}")

REST API Endpoints

Base URL: http://localhost:8501/v1/models/{model_name}

Endpoint                                  Method  Purpose
──────────────────────────────────────────────────────────────────────────
/v1/models/{name}                         GET     Check model status
/v1/models/{name}/versions/{ver}          GET     Check specific version
/v1/models/{name}:predict                 POST    Get predictions (latest version)
/v1/models/{name}/versions/{ver}:predict  POST    Get predictions (specific version)
/v1/models/{name}/metadata                GET     Get input/output signature
──────────────────────────────────────────────────────────────────────────

Inspecting the Model Signature

response = requests.get(
    'http://localhost:8501/v1/models/image_classifier/metadata'
)
metadata = response.json()
print(json.dumps(metadata, indent=2))

# Shows:
# - Input tensor name, shape, dtype
# - Output tensor name, shape, dtype
# Use these to format your request payload correctly

Batching Requests for Efficiency

# Send multiple samples in one request
batch_images = np.random.random((32, 224, 224, 3)).astype('float32')

payload = json.dumps({
    'instances': batch_images.tolist()
})

response = requests.post(
    'http://localhost:8501/v1/models/image_classifier:predict',
    data=payload,
    headers={'Content-Type': 'application/json'}
)

predictions = response.json()['predictions']
print(f"Batch predictions shape: {np.array(predictions).shape}")  # (32, 10)

Model Versioning: Zero-Downtime Updates

# Deploy a new version alongside the existing one
model_v2.save('serving_models/image_classifier/2/')

# TF Serving automatically:
# 1. Detects the new version directory
# 2. Loads version 2 into memory
# 3. Routes new requests to version 2
# 4. Unloads version 1 after a grace period

# Directory now:
# serving_models/image_classifier/1/  ← old version (being drained)
# serving_models/image_classifier/2/  ← new version (serving)

# Rollback is instant — just delete version 2 folder
# TF Serving switches back to version 1 automatically

Enabling TF Serving Batching Config

# Create a batching config file
batching_config = """
max_batch_size { value: 64 }
batch_timeout_micros { value: 5000 }
num_batch_threads { value: 4 }
max_enqueued_batches { value: 100 }
"""

with open('batching_config.txt', 'w') as f:
    f.write(batching_config)

# Start server with batching enabled
docker run -d -p 8501:8501 \
  --mount type=bind,source=$(pwd)/serving_models/image_classifier,target=/models/image_classifier \
  --mount type=bind,source=$(pwd)/batching_config.txt,target=/batching_config.txt \
  -e MODEL_NAME=image_classifier \
  tensorflow/serving \
  --enable_batching=true \
  --batching_parameters_file=/batching_config.txt

GPU Support in TF Serving

# Use the GPU-enabled TF Serving image
docker pull tensorflow/serving:latest-gpu

docker run -d --gpus all -p 8501:8501 \
  --mount type=bind,source=$(pwd)/serving_models/image_classifier,target=/models/image_classifier \
  -e MODEL_NAME=image_classifier \
  tensorflow/serving:latest-gpu

Production Deployment Checklist

Before deploying to production:
  ☐ Verify model accuracy on held-out test set
  ☐ Test the REST endpoint with representative inputs
  ☐ Test with edge cases (empty input, wrong shape, wrong dtype)
  ☐ Set up health check monitoring
  ☐ Configure request batching for throughput
  ☐ Enable GPU if latency is critical
  ☐ Set up model version rollback procedure
  ☐ Configure logging for prediction auditing

TensorFlow Serving transforms a trained model into a scalable, maintainable production API with minimal setup. The combination of SavedModel export, Docker deployment, and REST endpoint gives you everything needed to serve predictions to real applications at any scale. The next topic covers TensorFlow.js — the tool for running models directly in web browsers without any server.

Leave a Comment

Your email address will not be published. Required fields are marked *