Where the numbers come from
The base for each runtime is a hello-world JSON app measured with docker stats after 50 requests, with no limit and under 256 MB and 128 MB limits: idle memory for PHP, Python, Java, Spring Boot and .NET, measured. Python workers use the measured 1, 2 and 4 uvicorn workers (31.6, 87.0 and 147.6 MiB); other worker counts add 30.3 MiB each, the measured step. The 512 MB bar uses the no-limit numbers, the largest we saw.
Connection memory is PostgreSQL 18 with 50 connections: 1.66 MiB each running SELECT 1, 3.36 MiB after reading 100 tables and 3.80 MiB with 50 prepared statements, on top of 53.5 MiB for the server itself: how much memory a PostgreSQL connection uses, measured.
How to read it
- Fits means under 80% of the limit, tight 80 to 100%, does not fit over the limit, where the container is killed.
- A hello-world app is the floor. A real app with an ORM, templates and a few libraries uses more: put that in “your code and libraries”.
- More workers or threads serve more requests at once, but each Python worker is a full copy of your app and opens its own pool.
- On systemi, PostgreSQL runs outside your app container, so the connection memory is not counted in your app's memory.
Ready to deploy? See the getting started guide and the databases guide.