Setting optimal uWSGI options for django on NGINX

When your product is ready to release and it has to be deployed on production server you have to set optimal options.
NGINX does not need to be tunned, it just work as is installed but uWSGI not.
To reveal week points you need to run performance tests. Basically spam requests to you server.

Performance tests
To do it right you need use some existing solution or write simple script that will run many processes and requests your site or API.
For example lets assume that we have API with three different methods POST or GET.
First step should be setting initial uWSGI options.

uWSGI
NGINX serves your site using uWSGI and each request is handled by worker. So number of workers defines how many requests will be handled in same time.
So this is mos important parameter you need to define.
But lets imagine that you want to handle hundreds or thousands requests in same time (of course if your machine or VM is strong enough).
Setting hundreds workers (processes) will consume your memory. Here threads comes. First you need to enable-threads and than set number of threads per process.

So if you set 10 workers (processes) and 10 threads your server should be able to handle 100 requests in same time.
Number of requests per second depends on your request processing time.
If your request process 1s your server can handle 100 requests in second.
If your request process 0.1s your server can handle 1000 requests per second.

How to set them optimal?
You should run performance test on requests that consume most CPU/memory and increase wrorkers/threads number.

I would recommend init config (start point for perf tests):

workers = 4 * CPU cores number
enable-threads = True
threads = 10
Troubleshooting:

When you get memory usage problems you can use some options to control/recreate workers processes.

harakiri = 30 # kill worker if processing single requests lasts longer than 30s
reload-on-rss = 100 # kill worker if used more than 100 MB
evil-reload-on-rss = 1500 # kill dirty without waiting
worker-reload-mercy = 30 # time to wait for worker to reload
max-requests = 5000 # recreate worker after 5000 requests