{"id":34216640,"url":"https://github.com/danizen/fastapi-bakeoff","last_synced_at":"2026-03-13T13:33:27.817Z","repository":{"id":39608778,"uuid":"497394332","full_name":"danizen/fastapi-bakeoff","owner":"danizen","description":"A benchmark of fastapi docker images compared against Django and Spring Boot","archived":false,"fork":false,"pushed_at":"2023-03-14T05:07:54.000Z","size":149,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-06-20T00:28:34.538Z","etag":null,"topics":["asyncio","database"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danizen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-28T18:07:19.000Z","updated_at":"2023-03-14T14:58:42.000Z","dependencies_parsed_at":"2024-06-20T00:05:48.750Z","dependency_job_id":"950fe62f-b1c5-4ba5-9b80-5c69b7582cb8","html_url":"https://github.com/danizen/fastapi-bakeoff","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/danizen/fastapi-bakeoff","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danizen%2Ffastapi-bakeoff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danizen%2Ffastapi-bakeoff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danizen%2Ffastapi-bakeoff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danizen%2Ffastapi-bakeoff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danizen","download_url":"https://codeload.github.com/danizen/fastapi-bakeoff/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danizen%2Ffastapi-bakeoff/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30467803,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-13T11:00:43.441Z","status":"ssl_error","status_checked_at":"2026-03-13T11:00:23.173Z","response_time":60,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asyncio","database"],"created_at":"2025-12-15T22:12:40.392Z","updated_at":"2026-03-13T13:33:27.810Z","avatar_url":"https://github.com/danizen.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FastAPI Webapp Performance Test\n\n## Summary\n\nWeb applications are evolving away from serving templated HTML and towards being split into an API backend and a static HTML or JavaScript frontend. This repository studies the trade-offs between multiple python webapp architectures for the modern API backend. In trying fastapi, I am attempting to address three problems with Django WSGI:\n\n* Because of the GIL, multi-threading is just a way to avoid blocking and achieve concurrency, and so operating systems threads do not lead to true parallelism.  Thus asyncio and coroutines, with parallism using multiple pre-forked processes and horizontal scaling.\n* Without asyncio, the problems of managing database connections are made worse as we parallelize though multiple processes – the drivers are not built so that multiple processes can share database connections, and so pursuing parallelism through multiple processes introduces issues with connection pooling.  I think AWS RDS Proxy (or pgbouncer) are good solutions here, but would like to improve things on the application side. Oracle DRCP addresses this for Oracle, but is not implemented at my workplace.\n* The Django ORM is great for developers who don’t want to think about the database and don’t know SQL, but every ORM is a \"leaky abstraction\".  The best ORMs are aware of this, and strive to write very much like SQL to enable transfer learning. Django's ORM doesn’t fall into this camp.\n\nAnother nice to have which seems less essential to me is to have API schema generation and validation baked into the architecture. This is why fastapi is the async framework I am trying here. I know how to do this well with Django, and will reproduce the steps in the django implementation here.  All of these will follow the tenets of the twelve factor app.\n\n## Implementations\n\nEach of the sub-directories implements one combination of layers. One of these implementations will be a control cases:\n\n- java-spring - this combines Java/Spring 5/Spring boot and uses Liquibase to manage the schema\n\nThe following implementations are test cases:\n\n- django - combines gunicorn + uvicorn for Async scaling, djangorestframework, Django, and psycopg-binary.\n- fastapi-asyncpg - Combines fastapi, starlette, pydantic, and asyncpg.\n- fastapi-orm-asyncpg - Combines fastapi, starlette, pydantic, sqlalchemy ORM, and asyncpg\n\nAdditional data points in future:\n\n- fastapi-aiopg - Since aiopg is pure Python, we will test with pypy.\n- golang-bun - Combines golang with the leading Go ORM - bun\n\n\n## API\n\n- `/version` - tests basic response time\n- `/fibanacci/\u003cnumber\u003e` - tests what happens in asyncio when a tight computation is hit\n- `/contacts/` - retrieves a list of contacts.  This is carefully controlled so that it is paged,\ncan be filtered by last name, and requires 3 queries per page, always.\n- `/contacts/\u003cid\u003e` - retrieves one contact - also requires 3 queries per result.\n- `/types` - returns the contact types.  This is a smaller amount of JSON, and so JSON rendering should be less important. This is also a single SQL statement rather than involving joining and prefetching of related table data.\n\n## Hypothesis\n\nMy thinking is based on an analysis of `aiopg` vs `asyncpg`.  With `aiopg`, the API calls for the use of an `async for ` to return rows from a cursor. `asyncpg` has a different architecture where the `connection.fetch` method hides all concurrency for a block of data behind a single asynchronous coroutine:\n\n```python\nrecords = await connection.fetch(sql, *params)\n```\n\n`asyncpg` may then gain performance in two ways:\n- The coroutine yields only until the rows are ready, and then it can read and return multiple rows.\n- There is less marshalling from the `Record` type to native Python types.\n\nThis however leads to a productivity issue for the working engineer, in that a list of records returned by asyncpg must be marshalled into the shape needed for the API response.\n\nAPI calls which serve data from an RDBMS will be nearly as fast in async python as in golang. asyncpg will be faster than aiopg, but not dramatically. API calls which do significant computation will be much faster in golang.\n\n### What about PyPy\n\nPyPy is much, much faster than CPython. asyncpg is a Cython \nmodule, and may be slower in PyPy. aiopg should be faster,\nbut relies on psycopg-binary.  Probably a good idea to try\nto run the fastapi_aiopg on PyPy as a test. \n\nSome questions about PyPy:\n- How do I convince my DevOps to install PyPy?\n- How do I convince desktop support to install PyPy (gitpod may address this)?\n- How do I manage the availability of packages for \n  a particular developer?\n- How do I deploy into AWS Lambda - using Docker?\n\n## Other Relevant articles\n\nWhen I read up on benchmarks in the community, I see that the attraction to fastapi is not so much the speed as the ability to get your OpenAPI spec. done with Python\ntype annotations. I will still complete the benchmark and am still quite attracted to the option of fastapi + aiopg to see whether that will scale well in PyPy.\n\n- https://calpaterson.com/async-python-is-not-faster.html\n- https://blog.mirumee.com/django-fast-part-1-8d068a1b14bc\n- https://blog.mirumee.com/django-fast-part-2-d73a4ecd61f3\n- https://blog.miguelgrinberg.com/post/ignore-all-web-performance-benchmarks-including-this-one\n- https://github.com/psycopg/psycogreen/\n- https://techspot.zzzeek.org/2015/02/15/asynchronous-python-and-databases/\n- https://stackoverflow.com/questions/39815771/how-to-combine-celery-with-asyncio\n\nTest again.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanizen%2Ffastapi-bakeoff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanizen%2Ffastapi-bakeoff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanizen%2Ffastapi-bakeoff/lists"}