Nginx + Gunicorn is what we use. It has worked great for us. We have also tried uWSGI, a waitress for our production and Nginx + Gunicorn have been sure shot winners in terms of scalability and performance.
This is our gunicorn.conf that ensures gunicorn does not cause memory leaks
import multiprocessing
import os
import random
from getenv import env
def pre_fork(server, worker):
f = '/tmp/app-initialized'
open(f, 'w').close()
bind = 'unix:///tmp/nginx.socket'
workers = os.environ.get('WEB_CONCURRENCY',
(multiprocessing.cpu_count() * 1 - 1))
MAX_GUNICORN_REQUESTS = env('MAX_GUNICORN_REQUESTS', 100)
if MAX_GUNICORN_REQUESTS:
max_requests = MAX_GUNICORN_REQUESTS
MAX_REQUESTS_JITTER = env('MAX_REQUESTS_JITTER', 25)
if MAX_REQUESTS_JITTER:
max_requests_jitter = env('MAX_REQUESTS_JITTER', 25)