How Python web apps run in production
The development server you start with python manage.py runserver or flask run is not for production. In production a Python web app runs under an application server: gunicorn for WSGI apps (Django, Flask), and gunicorn with uvicorn workers — or uvicorn directly — for ASGI apps (FastAPI, Starlette, Django async). A web server in front handles HTTPS and static files. A managed Python host sets all of that up for you; your job is the code, the requirements and the settings.
Step 1 — Choose the plan and Python version
Python apps are limited mostly by memory, especially with several workers. Cloud Ninza Python plans: Starter (₹2,388 a year, 384 MB RAM, 1 app), Growth (₹4,188, 768 MB, 2 apps), Business (₹8,388, 1.5 GB) and Pro (₹14,388, 2 GB). Prices are before GST; 2 years save 5%, 3 years save 10%, 4 years save 15% and 5 years save 20%.
Pick the Python version your project uses — 3.10, 3.11, 3.12, 3.13 or 3.14. Django 5 needs 3.10 or newer; 3.12 is a safe default for new projects.
Step 2 — Prepare the project
Freeze your dependencies into requirements.txt (or use pyproject.toml). Move secrets into environment variables. For Django, read SECRET_KEY, DEBUG and ALLOWED_HOSTS from the environment, set STATIC_ROOT so collectstatic has somewhere to write, and keep DEBUG off in production.
- pip freeze > requirements.txt
- SECRET_KEY = os.environ['SECRET_KEY']
- ALLOWED_HOSTS from an environment variable
- STATIC_ROOT = BASE_DIR / 'staticfiles'
- DEBUG = False in production
Step 3 — Get the code onto the server
Upload a zip with the File manager and extract it into the app folder, use SSH with a key, or connect GitHub on the Git page. With Git, each push builds a new release with its own virtualenv, so a broken dependency never touches the live version; if the release fails its health check, the previous one stays live.
Step 4 — Choose the preset
On App settings, presets fill in the commands. Django: pip install -r requirements.txt plus gunicorn, then collectstatic and migrate as the build, and gunicorn yourproject.wsgi:application as the start. Flask: gunicorn app:app. FastAPI or Starlette: gunicorn main:app with uvicorn workers. There are also presets for any WSGI app, any ASGI app (Quart, Litestar) run by uvicorn, and a plain Python script or bot. Adjust the module names to match your project — what runs is what you save.
Every command runs inside the app's own virtualenv, so pip installs never touch the system Python.
Step 5 — Database and environment
Create PostgreSQL or MySQL/MariaDB on the Databases page and put the details in environment variables — DATABASE_URL or the individual settings your project reads. SQLite works for small sites. For MongoDB, use Atlas with 151.185.41.197/32 allowed. Paste your .env on App settings; values are stored privately.
Step 6 — Deploy and go live
Click Deploy: dependencies install, collectstatic and migrate run, and gunicorn starts with the workers set in the start command — two by default; raise it if your plan has memory to spare. Watch Logs for errors. Point A records for @ and www to the server IP on the Domains page; free SSL is issued automatically. Django admin, DRF APIs, FastAPI's /docs and Flask blueprints all work as they did locally.
What you get with Cloud Ninza Python hosting
Python hosting that handles the production plumbing:
- Python 3.10, 3.11, 3.12, 3.13 and 3.14, switchable per app
- Presets for Django, Flask, FastAPI, WSGI, ASGI and scripts
- A virtualenv per app (per release with Git deploys)
- gunicorn and uvicorn workers; restart on crash
- PostgreSQL and MySQL/MariaDB on the server; Atlas and external Redis by connection string
- Git deployments with health check and automatic rollback
- Environment variables, live build output, logs, cron jobs
- Free SSL issued automatically, terminal and key-only SSH
- Servers in India, isolated accounts, from ₹2,388 a year
Background jobs and Celery
Scheduled work — sending digests, clearing sessions, syncing data — runs well as cron jobs that call a management command or script. Celery with a broker needs Redis or RabbitMQ and permanent worker processes: use an external Redis for the broker and run workers as a second app on Growth or above, or move them to a cloud server when they grow.
Django in production: settings that matter
A handful of Django settings decide whether a site is production-ready. DEBUG must be False. ALLOWED_HOSTS must list your domain and www. CSRF_TRUSTED_ORIGINS needs your https:// origins on Django 4 and newer. SECURE_PROXY_SSL_HEADER should be set because HTTPS ends at the web server in front of gunicorn. Static files are collected into STATIC_ROOT by collectstatic and served efficiently; WhiteNoise is a simple, reliable way to serve them from the app. Run python manage.py check --deploy once — it lists anything you have missed.
- DEBUG = False
- ALLOWED_HOSTS and CSRF_TRUSTED_ORIGINS set
- SECURE_PROXY_SSL_HEADER for HTTPS behind the proxy
- collectstatic into STATIC_ROOT
- python manage.py check --deploy
FastAPI and async apps
FastAPI runs under uvicorn workers managed by gunicorn, which gives you multiple processes and automatic restarts. Use async database drivers (asyncpg for PostgreSQL, aiomysql or asyncmy for MySQL) with SQLAlchemy 2's async engine or an async ORM, and avoid blocking calls inside async routes — move them to a thread pool or a background job. The interactive /docs and /redoc pages work in production; protect them if your API is private.
Media uploads and static files
Keep user uploads (MEDIA_ROOT in Django) in a folder outside your code, and with Git deployments add it as a shared path so uploads survive every new release. For large or public media, object storage is the better long-term home. Static files — your CSS and JavaScript — are rebuilt by collectstatic on each deploy, so they always match the code.
Scheduled tasks for Django and Flask
Most apps need jobs that run on a timetable: sending reminder emails, clearing expired sessions, refreshing a cache, importing a feed. Add them on the Cron jobs page as commands that run inside your app's folder — for Django, a custom management command such as python manage.py send_reminders; for Flask or FastAPI, a small script that imports your app and does the work.
Make every scheduled job safe to run twice, log what it did, and keep it short; a job that runs for an hour every minute will overlap with itself. For heavier pipelines, move to a task queue with an external broker or to a cloud server where workers run permanently.
Django's clearsessions, Flask-APScheduler style in-process schedulers and FastAPI startup tasks all work too, but cron keeps scheduling visible in one place and survives app restarts.
Key takeaways
The short version, for anyone skimming:
- Production Python runs under gunicorn (WSGI) or uvicorn workers (ASGI).
- Pick Python 3.10–3.14; dependencies install into the app's own virtualenv.
- Presets for Django, Flask and FastAPI fill in install, build and start.
- PostgreSQL or MySQL on localhost; secrets in environment variables.
- Cloud Ninza Python hosting starts at ₹2,388 a year before GST.
Python Hosting from ₹2,388/year
Django, Flask and FastAPI on the Python version you choose, with their own isolated environment and a set RAM allowance. Python 3.10 to 3.14 · From 384 MB app RAM · Your code from Git or a ZIP.
Hosting from ₹99 a month on servers in India
WordPress, PHP, Node.js, Python and Java plans with free SSL and your choice of version. Create your account, pick a plan and pay by UPI, card or netbanking; your hosting is created automatically and you get your login by email, usually within minutes.