<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ayush Kumar</title>
    <description>The latest articles on DEV Community by Ayush Kumar (@ayush_kumar_085a0f2c54e3f).</description>
    <link>https://dev.to/ayush_kumar_085a0f2c54e3f</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3719463%2Fbaf9d251-b032-49a3-96f8-b015fd5d777a.jpeg</url>
      <title>DEV Community: Ayush Kumar</title>
      <link>https://dev.to/ayush_kumar_085a0f2c54e3f</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ayush_kumar_085a0f2c54e3f"/>
    <language>en</language>
    <item>
      <title>Fixing sqlalchemy.exc.MissingGreenlet in FastAPI and Async SQLAlchemy 2.0</title>
      <dc:creator>Ayush Kumar</dc:creator>
      <pubDate>Mon, 19 Jan 2026 11:07:51 +0000</pubDate>
      <link>https://dev.to/ayush_kumar_085a0f2c54e3f/fixing-sqlalchemyexcmissinggreenlet-in-fastapi-and-async-sqlalchemy-20-4gha</link>
      <guid>https://dev.to/ayush_kumar_085a0f2c54e3f/fixing-sqlalchemyexcmissinggreenlet-in-fastapi-and-async-sqlalchemy-20-4gha</guid>
      <description>&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You just migrated your FastAPI application to Async SQLAlchemy 2.0. You run your code, everything looks fine, and then bam. Your API crashes with this scary error message:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sqlalchemy.exc.MissingGreenlet: greenlet_spawn has not been called; can't call await_only() function.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you are seeing this, you are not alone. This is the #1 pitfall developers encounter when switching from synchronous to asynchronous database calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Cause&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This error happens when you try to access a Relationship attribute (like user.posts) that was not loaded in the original query.&lt;/p&gt;

&lt;p&gt;In the old synchronous world, SQLAlchemy would "lazily" load this data for you. It would silently pause your code, run a quick SQL query to get the posts, and then continue.&lt;/p&gt;

&lt;p&gt;In the Async world, this is illegal. SQLAlchemy cannot pause the event loop to run a synchronous "lazy load" query. Since it can't run the query, it crashes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution (Eager Loading)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To fix this, you must tell SQLAlchemy to fetch the related data upfront using "Eager Loading" strategies like selectinload or joinedload.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Broken Code (Lazy Loading):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Python&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# This query only fetches the User, not their posts
query = select(User).where(User.id == 1)
result = await session.execute(query)
user = result.scalar_one()

# CRASH HAPPENS HERE 💥
# SQLAlchemy tries to fetch 'posts' synchronously, but can't.
print(user.posts)

The Fix (Eager Loading): Import selectinload and add it to your query options.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Python
`
from sqlalchemy.orm import selectinload`

# Tell SQLAlchemy to fetch 'posts' immediately
query = select(User).options(selectinload(User.posts)).where(User.id == 1)

result = await session.execute(query)
user = result.scalar_one()

# Works perfectly! The data is already there.
print(user.posts)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Which Option Should You Use?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;selectinload: Best for One-to-Many relationships (e.g., User -&amp;gt; Posts). It runs two separate queries (one for users, one for posts) which is often faster for lists.&lt;/p&gt;

&lt;p&gt;joinedload: Best for Many-to-One relationships (e.g., Post -&amp;gt; Author). It runs a single query with a SQL JOIN.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Personal Tip&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want to prevent this error from ever happening again, you can disable lazy loading entirely in your model configuration. This forces you to be explicit about your queries, which is better for performance anyway.&lt;/p&gt;

&lt;p&gt;Python&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# In your model definition
class User(Base):
    __tablename__ = "users"
    # Raise an error if you forget to load data
    posts = relationship("Post", lazy="raise_on_sql")

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next Steps&lt;/p&gt;

&lt;p&gt;Now that you have fixed your relationships, make sure your entire AsyncEngine is configured correctly. Check out my Complete Guide to &lt;a href="https://www.logiclooptech.dev/modern-backend-building-high-performance-async-apis-with-fastapi-and-sqlalchemy-20" rel="noopener noreferrer"&gt;Async FastAPI &amp;amp; SQLAlchemy 2.0 for a full production setup&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>fastapi</category>
      <category>sql</category>
      <category>help</category>
    </item>
  </channel>
</rss>
