As far as I read all over the Internet - the best practice for deploying Flask/Django applications is to put the behind a web server such as nginx and bundle them with a pre-fork server such as gunicorn or uWSGI.
This is good for many reasons, such as ssl-termination, protection against HTTP attacks (nginx), forking to threads for concurrency, restarting the application after a memory leak, or other exceptions (gunicron).
I want to deploy an internal API micro-service on sanic with pm2, as it's not customer facing, but rather will only be called from internal services the SSH termination and protection against HTTP attacks is irrelevant, the concurrency is guaranteed by sanic's asyncio nature and the restarting upon exception is handled by pm2.
Do I still need gunicorn and nginx? Can't I just run the application process as is and let it talk directly to its callers?
You absolutely do not need to have gunicorn in front of your stack. Sanic can run just fine without having a web server in front of it since it has its own internal server.
I still would advocate for using nginx to terminate TLS and to handle static files (even though sanic could do both of these), since it is efficient at it.
here's a link to another answer I've given on the same question: https://community.sanicframework.org/t/gunicorn-uwsgi-vs-build-in-http-server/47/2?u=ahopkins