FastAPI supports custom response classes, among them there is support for multiple JSON response implementations. Default is JSONResponse but orjson and ujson are available as well. Both have their benchmark / performance testclaiminig they are the fastest, but worths checking for the given usecase.
Note: FastAPI supports different response classes, but request parsing is done by Starlette where you don’t have control over which JSON implementation to be used
By default, FastAPI uses the base JSON implementation, let’s see the results:
Test attribute | Test run 1 | Test run 2 | Test run 3 | Average |
---|---|---|---|---|
Requests per second | 9.5 | 9.11 | 9.81 | 9.4733 |
Time per request [ms] | 10521.5 | 10979.8 | 10191.4 | 10564.2 |
Note: There are some specialities requre attention
Test attribute | Test run 1 | Test run 2 | Test run 3 | Average | Difference to baseline |
---|---|---|---|---|---|
Requests per second | 9.61 | 10.07 | 9.46 | 9.7133 | 2.53 % |
Time per request [ms] | 10401 | 9928.04 | 10572.4 | 10300.5 | 263.75 ms |
Note: Just like orjson this has its own speciality
Test attribute | Test run 1 | Test run 2 | Test run 3 | Average | Difference to baseline |
---|---|---|---|---|---|
Requests per second | 9.42 | 9.95 | 9.19 | 9.52 | 0.49 % |
Time per request [ms] | 10620.7 | 10047.3 | 10878 | 10515.3 | 48.9 ms |
Please note that you can have different JSON response class for each API endpoint as shown in the FastAPI docs:
from fastapi import FastAPI
from fastapi.responses import UJSONResponse
app = FastAPI()
@app.get("/items/", response_class=UJSONResponse)
async def read_items():
return [{"item_id": "Foo"}]