A production-ready, high-performance FastAPI microservice for image generation using the Z-Image-Turbo diffusion model. Optimized for GPU execution with NVIDIA CUDA support, API key protection, and comprehensive logging.
- FastAPI Framework: Modern async Python web framework with automatic OpenAPI documentation
- GPU-Optimized: CUDA 12.1 support with memory-efficient inference (fp16, bfloat16, fp8)
- Singleton Model Loading: Efficient model management with thread-safe singleton pattern
- API Key Authentication: Secure X-API-Key header-based authentication
- Health Monitoring: Public health endpoint with GPU/memory metrics
- Docker Ready: Production-grade Dockerfile with multi-stage builds
- Comprehensive Logging: Detailed logs including GPU memory tracking
- Error Handling: Graceful CUDA OOM handling and validation
- Pydantic Validation: Strong type hints and request validation
- GPU: NVIDIA GPU with CUDA 12.1 support (Tesla T4, V100, A100, H100, etc.)
- CPU: 4+ cores recommended
- RAM: 16GB minimum, 32GB+ recommended
- VRAM: 6GB minimum (for fp16), 12GB+ recommended
- Docker: With NVIDIA Container Runtime support
- Python: 3.10+ (if running locally)
- CUDA: 12.1 (automatically included in Docker image)
sdxl-zimage-api/
βββ app/
β βββ __init__.py # Package initialization
β βββ main.py # FastAPI routes and application setup
β βββ config.py # Pydantic Settings for configuration
β βββ auth.py # API Key validation
β βββ model_pipeline.py # Model engine and inference logic
βββ Dockerfile # Multi-stage production Docker setup
βββ requirements.txt # Python dependencies
βββ .env.example # Example environment configuration
βββ README.md # This file
Copy .env.example to .env and update values:
cp .env.example .envKey environment variables:
API_KEY: Secret key for X-API-Key authentication (change in production!)MODEL_ID: Hugging Face model repository ID (default:stabilityai/sd-turbo)PRECISION: Model precision -fp32,fp16,bfloat16, orfp8GPU_DEVICE: CUDA device ID (default:cuda)MAX_QUEUE_SIZE: Maximum concurrent requests (default:10)
See .env.example for all available options.
docker build -t z-image-turbo-api:latest .docker run --gpus all \
--env-file .env \
-p 8000:8000 \
z-image-turbo-api:latestCreate docker-compose.yml:
version: '3.8'
services:
api:
build: .
container_name: z-image-turbo-api
env_file: .env
ports:
- "8000:8000"
volumes:
- ./models_cache:/home/appuser/.cache/huggingface # Cache models
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
restart: unless-stoppedRun with:
docker-compose up -d# Create virtual environment
python3.10 -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt# Set environment variables
export API_KEY="test-key-12345"
export MODEL_ID="stabilityai/sd-turbo"
# Run server
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reloadhttp://localhost:8000
All endpoints (except /health) require the X-API-Key header:
X-API-Key: your-secret-api-key
GET /healthResponse:
{
"status": "healthy",
"model_ready": true,
"device": "cuda",
"gpu_memory": {
"allocated_gb": 5.2,
"reserved_gb": 6.0,
"available_gb": 16.0
},
"system_memory_gb": 8.5
}POST /api/v1/generate
Content-Type: application/json
X-API-Key: your-secret-api-key
{
"prompt": "A futuristic city with neon lights, high resolution",
"negative_prompt": "blurry, low quality, distorted",
"width": 768,
"height": 768,
"num_inference_steps": 8,
"guidance_scale": 1.5,
"return_type": "base64"
}Response (return_type: "base64"):
{
"success": true,
"image": "iVBORw0KGgoAAAANSUhEUgAA...",
"format": "png",
"size": {
"width": 768,
"height": 768
},
"prompt": "A futuristic city with neon lights, high resolution",
"inference_steps": 8
}Response (return_type: "binary"):
Raw PNG image data with Content-Type: image/png
# Health check
curl http://localhost:8000/health
# Generate image with base64 response
curl -X POST http://localhost:8000/api/v1/generate \
-H "Content-Type: application/json" \
-H "X-API-Key: your-secret-api-key" \
-d '{
"prompt": "A serene mountain landscape at sunset",
"width": 768,
"height": 768,
"num_inference_steps": 8,
"guidance_scale": 1.5
}' > response.json
# Generate image with binary response (save directly)
curl -X POST http://localhost:8000/api/v1/generate \
-H "Content-Type: application/json" \
-H "X-API-Key: your-secret-api-key" \
-d '{
"prompt": "A robot painting a masterpiece",
"width": 768,
"height": 768,
"num_inference_steps": 8,
"return_type": "binary"
}' > generated_image.pngimport requests
import json
from PIL import Image
from io import BytesIO
import base64
API_KEY = "your-secret-api-key"
BASE_URL = "http://localhost:8000"
# Check health
response = requests.get(f"{BASE_URL}/health")
print(response.json())
# Generate image
payload = {
"prompt": "A cyberpunk samurai warrior",
"width": 768,
"height": 768,
"num_inference_steps": 8,
"guidance_scale": 1.5,
"return_type": "base64"
}
headers = {"X-API-Key": API_KEY}
response = requests.post(
f"{BASE_URL}/api/v1/generate",
json=payload,
headers=headers
)
if response.status_code == 200:
data = response.json()
# Decode base64 image
image_data = base64.b64decode(data["image"])
image = Image.open(BytesIO(image_data))
image.save("generated.png")
print("Image saved as generated.png")
else:
print(f"Error: {response.status_code}")
print(response.json())const API_KEY = "your-secret-api-key";
const BASE_URL = "http://localhost:8000";
async function generateImage() {
const payload = {
prompt: "A majestic dragon flying over mountains",
width: 768,
height: 768,
num_inference_steps: 8,
guidance_scale: 1.5,
return_type: "base64"
};
const response = await fetch(`${BASE_URL}/api/v1/generate`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": API_KEY
},
body: JSON.stringify(payload)
});
if (response.ok) {
const data = await response.json();
console.log("Image generated successfully!");
console.log(`Size: ${data.size.width}x${data.size.height}`);
// Download or display base64 image
return data.image;
} else {
console.error(`Error: ${response.status}`, await response.json());
}
}
generateImage();-
API Key Protection
- Change
API_KEYin.envfor production - Use strong, random API keys (min 32 characters)
- Rotate keys periodically
- Change
-
Network Security
- Deploy behind a reverse proxy (nginx, traefik)
- Use HTTPS/TLS in production
- Implement rate limiting
- Use firewall rules to restrict access
-
GPU Security
- Run container with
--gpus all(not--privileged) - Use read-only filesystem where possible
- Drop unnecessary Linux capabilities
- Run container with
-
Resource Limits
- Set memory limits in Docker
- Configure
MAX_QUEUE_SIZEto prevent abuse - Implement request timeouts
- num_inference_steps: Lower = faster but lower quality (try 4-8)
- guidance_scale: Lower values speed up inference (try 1.0-2.0)
- Image size: Smaller images are faster (try 512x512)
- precision: Use
fp16orbfloat16to reduce memory - enable_xformers: Significantly reduces VRAM usage
- batch_size: Currently supports single image generation
# In production Docker, use:
ENV CUDA_VISIBLE_DEVICES=0 # Single GPU
ENV CUDA_LAUNCH_BLOCKING=0 # Async GPU launchesRuntimeError: CUDA out of memory
Solutions:
- Reduce
num_inference_steps(try 4-6) - Reduce image dimensions (try 512x512)
- Enable
ENABLE_XFORMERS=true - Use
PRECISION=fp8instead of fp16
OSError: Can't load model...
Solutions:
- Check internet connection
- Pre-download model:
huggingface-cli download stabilityai/sd-turbo - Mount model cache volume in Docker
RuntimeError: No CUDA GPUs available
Solutions:
- Verify NVIDIA GPU:
nvidia-smi - Install NVIDIA Container Runtime:
nvidia-ctk runtime configure --runtime=docker - Restart Docker:
systemctl restart docker - Ensure
--gpus allflag is set
docker logs -f z-image-turbo-api# Successful startup
INFO: Uvicorn running on http://0.0.0.0:8000
INFO: Model loaded successfully on device: cuda
# Inference
INFO: GPU Memory before inference: allocated=4.2GB, reserved=5.0GB
INFO: GPU Memory after inference: allocated=0.2GB, reserved=5.0GB
# Errors
ERROR: CUDA out of memory error during inference
ERROR: Model engine not ready
Once server is running:
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
- OpenAPI Schema: http://localhost:8000/openapi.json
# Launch g4dn.xlarge or g5.xlarge instance
# Install Docker and NVIDIA Container Runtime
# Build and run
docker build -t z-image-turbo-api:latest .
docker run --gpus all --env-file .env -p 8000:8000 z-image-turbo-api:latestapiVersion: v1
kind: Pod
metadata:
name: z-image-turbo
spec:
containers:
- name: api
image: z-image-turbo-api:latest
envFrom:
- configMapRef:
name: api-config
ports:
- containerPort: 8000
resources:
limits:
nvidia.com/gpu: 1
requests:
memory: "16Gi"
cpu: "4"server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 300s;
proxy_connect_timeout 300s;
}
}Specify your license here (e.g., MIT, Apache 2.0)
Contributions welcome! Please ensure:
- Code follows existing style
- Type hints are complete
- Error handling is comprehensive
- Documentation is updated
For issues, questions, or feature requests, please open an issue on GitHub.
Made with β€οΈ for high-performance image generation