Image

Daniel Roy Greenfeld: Using Asyncpg with FastAPI and Air

Recently I've was on a few projects using PostgreSQL where SQLAlchemy and SQLModel felt like overkill. Instead of using those libraries I leaned on writing SQL queries and running those directly inasyncpginstead of using an ORM powered by asyncpg.

Here's how I got it to work

Defined a lifespan function for ASGIApp

Starlette ASGIApp frameworks like FastAPI (and by extensionAir) can leverage lifespan functions, which are generators. I've commented thelifespanobject so the

Using the lifespan function

Just add thelifespanfunction to the app when it is instantiated.

Using the lifespan function for FastAPI projects

All you have to do is pass thelifespancallable to the FastAPI app instantiation.

Using the lifespan function for Air projects

Air is powered by FastAPI (and Starlette), so uses thislifespanfunction the same way as FastAPI.

Incoming data

Changing data requires use of theconn.executefunction. Of course these examples will show how to usepydanticto validate the incoming data before we allow it to touch our database.

Adding data with FastAPI via asyncpg

As part of the request process for REST API, FastAPI uses pydantic to validate incoming data. This results a delightfully small view for accepting data.

Adding data with Air via asyncpg

There's no consistent standard within HTML for how to construct a form, much less respond to a bad implementation. Therefore in order to handle incoming data Air needs a bit more code than FastAPI.

AirForms supports reporting of bad data. I'll cover how to do that in follow-up article.

https://daniel.feldroy.com/posts/2025-10-using-asyncpg-with-fastapi-and-air