Deployment
Deploy EVOID applications to production.
Quick Deploy
evo service run api
This starts the server at http://0.0.0.0:8000.
Production Setup
Uvicorn with Workers
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
Worker count: CPU cores * 2 + 1
Systemd Service
[Unit]
Description=EVOID API Service
After=network.target
[Service]
Type=exec
User=www-data
WorkingDirectory=/opt/my-api
ExecStart=/opt/my-api/.venv/bin/evo service run api
Restart=always
[Install]
WantedBy=multi-user.target
sudo systemctl enable my-api
sudo systemctl start my-api
Docker
FROM python:3.13-slim
WORKDIR /app
COPY pyproject.toml .
RUN pip install uv && uv sync
COPY . .
EXPOSE 8000
CMD ["evo", "service", "run", "api"]
docker build -t my-api .
docker run -p 8000:8000 my-api
Docker Compose
services:
api:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://...
restart: unless-stopped
SSL / HTTPS
Nginx Reverse Proxy
server {
listen 443 ssl;
server_name myapi.example.com;
ssl_certificate /etc/letsencrypt/live/myapi.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myapi.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Health Check
from evoid.adapters.asgi import get
from evoid.web.route import Service
app = Service("my-api")
@get("/health", level="ephemeral")
async def health() -> dict:
return {"status": "healthy"}
Environment Variables
import os
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///db.sqlite")
REDIS_URL = os.getenv("REDIS_URL", "redis://localhost")
DEBUG = os.getenv("DEBUG", "false").lower() == "true"
Graceful Shutdown
import signal
import sys
def shutdown(sig, frame):
# Cleanup resources
sys.exit(0)
signal.signal(signal.SIGTERM, shutdown)
signal.signal(signal.SIGINT, shutdown)
Monitoring
Process Management
systemctl status my-api
journalctl -u my-api -f
systemctl restart my-api
Metrics
from evoid.engines.metrics import simple as metrics
metrics.increment("requests.total")
start = metrics.timer_start("request.duration")
# ... handle request
metrics.timer_stop("request.duration", start)
Best Practices
- Use
level="ephemeral"for health check endpoints - Set appropriate timeouts per Intent level
- Use structured logging in production
- Monitor pipeline execution times
- Use the message bus for inter-service communication, not HTTP