Skip to main content

Overview

Deploying Framefox applications to production requires careful configuration and optimization. This guide covers best practices for running Framefox in production environments.

Production Checklist

Before deploying to production, ensure you’ve completed these critical steps:

Security

  • Set a strong SECRET_KEY in your environment variables
  • Configure secure session management
  • Enable HTTPS and set cookie.secure to true
  • Review and configure CORS settings appropriately
  • Disable debug mode by setting APP_ENV=prod
  • Configure proper firewall rules

Performance

  • Configure production-grade database connection pooling
  • Enable appropriate caching strategies
  • Optimize static file serving
  • Configure proper logging levels
  • Set up monitoring and error tracking (e.g., Sentry)

Environment

  • Use environment variables for sensitive configuration
  • Set APP_ENV=prod in your .env file
  • Configure production database credentials
  • Set up proper backup strategies

Running with Uvicorn

Framefox is built on FastAPI and runs on Uvicorn, a lightning-fast ASGI server.

Basic Production Command

uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
uvicorn main:app \
  --host 0.0.0.0 \
  --port 8000 \
  --workers 4 \
  --proxy-headers \
  --forwarded-allow-ips='*' \
  --no-access-log
Parameters Explained:
  • --host 0.0.0.0: Bind to all network interfaces
  • --port 8000: Port to listen on
  • --workers 4: Number of worker processes (typically 2-4 per CPU core)
  • --proxy-headers: Trust X-Forwarded headers from reverse proxy
  • --forwarded-allow-ips='*': Allow forwarded IPs from any source (adjust for security)
  • --no-access-log: Disable access logs (use reverse proxy logs instead)

Worker Count Calculation

A good starting point for worker count:
workers = (2 x num_cores) + 1
For a 4-core server:
uvicorn main:app --workers 9

Process Management with Gunicorn

For production, use Gunicorn with Uvicorn workers:
gunicorn main:app \
  --workers 4 \
  --worker-class uvicorn.workers.UvicornWorker \
  --bind 0.0.0.0:8000 \
  --access-logfile - \
  --error-logfile -

Install Gunicorn

pip install gunicorn

Systemd Service

Create a systemd service for automatic startup and management.

Service File: /etc/systemd/system/framefox.service

[Unit]
Description=Framefox Application
After=network.target

[Service]
Type=notify
User=www-data
Group=www-data
WorkingDirectory=/var/www/framefox
Environment="PATH=/var/www/framefox/venv/bin"
ExecStart=/var/www/framefox/venv/bin/gunicorn main:app \
  --workers 4 \
  --worker-class uvicorn.workers.UvicornWorker \
  --bind 0.0.0.0:8000
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Enable and Start Service

sudo systemctl daemon-reload
sudo systemctl enable framefox
sudo systemctl start framefox
sudo systemctl status framefox

Reverse Proxy Configuration

Nginx

Recommended Nginx configuration:
server {
    listen 80;
    server_name yourdomain.com;

    # Redirect HTTP to HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name yourdomain.com;

    # SSL Configuration
    ssl_certificate /etc/ssl/certs/your-cert.pem;
    ssl_certificate_key /etc/ssl/private/your-key.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    # Security Headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # Static files
    location /public {
        alias /var/www/framefox/public;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # Proxy to Framefox
    location / {
        proxy_pass http://127.0.0.1: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_redirect off;
        proxy_buffering off;
    }
}

Apache

<VirtualHost *:80>
    ServerName yourdomain.com
    Redirect permanent / https://yourdomain.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName yourdomain.com

    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/your-cert.pem
    SSLCertificateKeyFile /etc/ssl/private/your-key.pem

    # Security Headers
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"

    # Proxy Configuration
    ProxyPreserveHost On
    ProxyPass /public !
    ProxyPass / http://127.0.0.1:8000/
    ProxyPassReverse / http://127.0.0.1:8000/

    # Static files
    Alias /public /var/www/framefox/public
    <Directory /var/www/framefox/public>
        Require all granted
        ExpiresActive On
        ExpiresDefault "access plus 30 days"
    </Directory>
</VirtualHost>

Performance Tuning

Database Connection Pooling

Configure proper connection pooling in your config/orm.yaml:
database:
  url: ${DATABASE_URL}
  pool_size: 20
  max_overflow: 10
  pool_pre_ping: true
  pool_recycle: 3600

Logging Configuration

Optimize logging for production in config/debug.yaml:
debug:
  logging:
    level: INFO  # or WARNING for less verbose
    file_path: var/log/app.log
    max_size: 100  # MB
    backup_count: 10
  profiler:
    enabled: false  # Disable in production

Session Storage

Use Redis for session storage in production:
application:
  session:
    secret_key: ${SESSION_SECRET_KEY}
    redis:
      url: ${REDIS_URL}
      prefix: "session:"
      db: 0

Monitoring and Error Tracking

Sentry Integration

Configure Sentry for error tracking in config/debug.yaml:
debug:
  sentry:
    dsn: ${SENTRY_DSN}
    environment: production
    sample_rate: 1.0
    traces_sample_rate: 0.1  # 10% of requests
Set the SENTRY_DSN environment variable:
SENTRY_DSN=https://[email protected]/project

Application Monitoring

Monitor key metrics:
  • Response times: Track endpoint performance
  • Error rates: Monitor failed requests
  • Database performance: Query times and connection pool usage
  • Resource usage: CPU, memory, disk I/O
  • Worker health: Process status and restarts

Health Check Endpoint

Implement a health check endpoint:
from framefox.core.routing.decorator.route import Route
from framefox.core.controller.abstract_controller import AbstractController

class HealthController(AbstractController):
    
    @Route("/health", "health.check", methods=["GET"])
    async def check(self):
        return {"status": "healthy", "version": "1.0.0"}

Security Best Practices

Environment Variables

Never commit sensitive data. Use environment variables:
# .env (DO NOT COMMIT)
APP_ENV=prod
SECRET_KEY=your-very-secure-secret-key-here
DATABASE_URL=postgresql://user:password@localhost/dbname
REDIS_URL=redis://localhost:6379/0
SENTRY_DSN=https://[email protected]/project
Configure secure cookies in config/application.yaml:
application:
  cookie:
    secure: true
    http_only: true
    same_site: lax
    max_age: 3600

CSRF Protection

Framefox includes built-in CSRF protection. Ensure it’s enabled for state-changing operations.

HTTPS Only

Always use HTTPS in production:
  • Obtain SSL certificates (Let’s Encrypt is free)
  • Configure your reverse proxy for HTTPS
  • Set cookie.secure: true
  • Enable HSTS headers

Deployment Strategies

Blue-Green Deployment

  1. Deploy new version to separate environment
  2. Run tests on new environment
  3. Switch traffic to new environment
  4. Keep old environment for quick rollback

Rolling Updates

  1. Deploy to one server at a time
  2. Verify each server before proceeding
  3. Minimize downtime with load balancer

Database Migrations

Run migrations before deploying new code:
framefox database upgrade
For zero-downtime deployments:
  1. Make migrations backward-compatible
  2. Deploy code that works with old and new schema
  3. Run migration
  4. Deploy code optimized for new schema

Backup and Recovery

Database Backups

# PostgreSQL
pg_dump -U username dbname > backup.sql

# MySQL
mysqldump -u username -p dbname > backup.sql

Automated Backups

Set up cron jobs for regular backups:
# Daily backup at 2 AM
0 2 * * * /path/to/backup-script.sh

Session Data

If using Redis, enable RDB or AOF persistence:
# redis.conf
save 900 1
save 300 10
save 60 10000

Scaling Considerations

Horizontal Scaling

  • Use a load balancer (Nginx, HAProxy, AWS ALB)
  • Ensure session storage is shared (Redis)
  • Use external database, not SQLite
  • Stateless application design

Vertical Scaling

  • Increase worker count based on CPU cores
  • Allocate more memory for caching
  • Optimize database queries
  • Use connection pooling

Troubleshooting

High Memory Usage

  • Reduce worker count
  • Check for memory leaks
  • Optimize database queries
  • Review application code for inefficiencies

Slow Response Times

  • Check database query performance
  • Review Sentry traces
  • Optimize template rendering
  • Enable caching where appropriate
  • Use database query profiling

Worker Crashes

  • Check logs: journalctl -u framefox -n 100
  • Review Sentry for exceptions
  • Verify database connectivity
  • Check resource limits (ulimit)

Next Steps

Docker Deployment

Containerize your Framefox application

Environment Variables

Manage configuration and secrets

Build docs developers (and LLMs) love