Skip to content

FastAPI GraphQL Strawberry Fix

DodaTech Updated 2026-06-24 3 min read

In this tutorial, you'll learn about FastAPI GraphQL Strawberry Fix. We cover key concepts, practical examples, and best practices.

The Problem

Your frontend team wants GraphQL flexibility, but your backend is built with FastAPI REST endpoints. Strawberry GraphQL integrates with FastAPI but requires proper schema setup.

Quick Fix

Wrong — no GraphQL integration

# REST endpoints for every query variation
@app.get("/users")
@app.get("/users/{user_id}")
@app.get("/users/{user_id}/posts")
@app.get("/users/{user_id}/posts/{post_id}/comments")

Output: REST endpoints multiply for each new query pattern. Over-fetching and under-fetching are common.

Correct — Strawberry GraphQL with FastAPI

import strawberry
from fastapi import FastAPI
from strawberry.fastapi import GraphQLRouter

@strawberry.type
class User:
    id: int
    name: str
    email: str

@strawberry.type
class Query:
    @strawberry.field
    async def user(self, id: int) -> User:
        user = await fetch_user(id)
        return User(id=user.id, name=user.name, email=user.email)

    @strawberry.field
    async def users(self) -> List[User]:
        users = await fetch_all_users()
        return [User(id=u.id, name=u.name, email=u.email) for u in users]

schema = strawberry.Schema(query=Query)
graphql_app = GraphQLRouter(schema)

app = FastAPI()
app.include_router(graphql_app, prefix="/graphql")

Output: Single /<a href="/apis/graphql/">graphql</a> endpoint. Clients query exactly the fields they need.

Mutations

@strawberry.type
class Mutation:
    @strawberry.mutation
    async def create_user(self, name: str, email: str) -> User:
        user = await create_user_in_db(name, email)
        return User(id=user.id, name=user.name, email=user.email)

    @strawberry.mutation
    async def delete_user(self, id: int) -> bool:
        await delete_user_from_db(id)
        return True

schema = strawberry.Schema(query=Query, mutation=Mutation)

Authentication with Strawberry

from fastapi import Depends
from strawberry.fastapi import BaseContext

class CustomContext(BaseContext):
    def __init__(self, user):
        self.user = user

async def get_context(user=Depends(get_current_user)):
    return CustomContext(user=user)

graphql_app = GraphQLRouter(schema, context_getter=get_context)

@strawberry.type
class Query:
    @strawberry.field
    async def me(self, info: strawberry.Info) -> User:
        return info.context.user

DataLoader for N+1 prevention

from strawberry.dataloader import DataLoader

async def load_users(ids: List[int]) -> List[User]:
    users = await fetch_users_by_ids(ids)
    return [users[i] for i in ids]

class CustomContext(BaseContext):
    def __init__(self):
        self.user_loader = DataLoader(load_users)

@strawberry.type
class Query:
    @strawberry.field
    async def user(self, id: int, info: strawberry.Info) -> User:
        return await info.context.user_loader.load(id)

Enums and inputs

from enum import Enum
import strawberry

@strawberry.enum
class UserRole(Enum):
    ADMIN = "admin"
    USER = "user"
    GUEST = "guest"

@strawberry.input
class UserFilter:
    role: UserRole | None = None
    is_active: bool | None = None

Prevention

  • Use Strawberry's DataLoader to batch database queries and prevent N+1.
  • Define context getter for authentication and database sessions.
  • Use strawberry.input for complex mutation arguments.

Common Mistakes with graphql strawberry

  1. Non-exhaustive pattern matches that compile with warnings then crash at runtime
  2. Misunderstanding that String is [Char] with poor performance for large text operations
  3. Using foldl instead of foldl' causing stack overflow on large lists

These mistakes appear frequently in real-world FASTAPI code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### Why Strawberry over Graphene?

Strawberry uses Python type hints and Pydantic-like syntax. It natively supports async, DataLoader, and FastAPI integration. Graphene is older and less actively maintained.

Can I mix REST and GraphQL?

Yes. FastAPI supports both. Use REST for simple CRUD and GraphQL for complex nested queries.

How do I handle file uploads with Strawberry?

Strawberry supports file uploads via Upload scalar. Send multipart form data with the operations and map fields.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro