Last modified: Dec 02, 2025 By Alexander Williams
Build GraphQL APIs with Python FastAPI Strawberry
Modern APIs need speed and flexibility. GraphQL is a powerful query language. It lets clients request exactly the data they need. Python developers can now build these APIs easily. Combine FastAPI and Strawberry for the best results.
FastAPI is a modern Python web framework. It is very fast and easy to use. It offers automatic API documentation. Strawberry is a GraphQL library for Python. It uses Python type hints to define the schema. This combination is perfect for building robust APIs.
This guide will walk you through the process. You will learn to set up a project. You will define a GraphQL schema. You will run queries and mutations. Let's start building.
Why FastAPI and Strawberry?
FastAPI is built for performance. It uses Starlette and Pydantic under the hood. It supports asynchronous endpoints natively. This makes it ideal for high-performance applications. You can also add features like CORS Middleware to FastAPI Apps easily.
Strawberry is a code-first GraphQL library. You write Python classes to define your schema. The library generates the GraphQL schema from your code. This approach is intuitive for Python developers. It ensures your schema is always in sync.
Together, they provide a seamless development experience. You get automatic validation, serialization, and documentation. Your API will be both fast and developer-friendly.
Project Setup and Installation
First, create a new project directory. Set up a virtual environment. This keeps your dependencies isolated. Install the required packages.
# Create and activate a virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install FastAPI, Strawberry, and an ASGI server
pip install fastapi strawberry-graphql uvicorn
The main packages are fastapi and strawberry-graphql. Uvicorn is an ASGI server. It will run your FastAPI application.
Defining Your First GraphQL Schema
Create a file named main.py. Start by importing the necessary modules. Define a simple data model using Strawberry's @strawberry.type decorator.
import strawberry
from fastapi import FastAPI
from strawberry.fastapi import GraphQLRouter
# Define a GraphQL type for a Book
@strawberry.type
class Book:
title: str
author: str
# Define the Query class
@strawberry.type
class Query:
@strawberry.field
def hello(self) -> str:
return "Hello, GraphQL World!"
@strawberry.field
def get_book(self) -> Book:
# Return a sample book object
return Book(title="The FastAPI Book", author="Jane Developer")
# Create the Strawberry schema
schema = strawberry.Schema(query=Query)
# Create the FastAPI app and attach the GraphQL router
app = FastAPI(title="FastAPI Strawberry GraphQL")
graphql_app = GraphQLRouter(schema)
app.include_router(graphql_app, prefix="/graphql")
# Root endpoint
@app.get("/")
def read_root():
return {"message": "Navigate to /graphql for the GraphQL playground"}
We defined a Book type with title and author. The Query class holds our GraphQL fields. The hello field returns a string. The get_book field returns a Book object. The strawberry.Schema function creates the schema.
The GraphQLRouter from Strawberry integrates with FastAPI. We mount it at the "/graphql" path. The root endpoint gives a simple message.
Running the API Server
Start the development server using Uvicorn. Open your terminal in the project directory. Run the following command.
uvicorn main:app --reload
The server will start on http://localhost:8000. The --reload flag enables auto-reload on code changes. This is useful during development.
Open your browser. Go to http://localhost:8000/graphql. You will see the GraphQL playground. This is an interactive interface. You can test your queries here.
Executing Your First GraphQL Query
In the playground, try a simple query. Type the query on the left panel. Click the play button to execute.
query {
hello
getBook {
title
author
}
}
This query asks for two fields. The hello string and the getBook object. We specify we want the book's title and author. The server will respond with structured JSON.
{
"data": {
"hello": "Hello, GraphQL World!",
"getBook": {
"title": "The FastAPI Book",
"author": "Jane Developer"
}
}
}
The response matches the query shape exactly. This is the power of GraphQL. The client controls the response structure. No over-fetching or under-fetching of data.
Adding Mutations for Data Changes
Queries fetch data. Mutations change data. Let's add a mutation to add a new book. We need a Mutation class. Use the @strawberry.type and @strawberry.field decorators.
# In-memory store for books (for demonstration)
books_db = []
@strawberry.type
class Mutation:
@strawberry.field
def add_book(self, title: str, author: str) -> Book:
# Create a new book and store it
new_book = Book(title=title, author=author)
books_db.append(new_book)
return new_book
# Update the schema to include mutations
schema = strawberry.Schema(query=Query, mutation=Mutation)
# The FastAPI app setup remains the same
We created a simple list books_db to store books. The add_book mutation takes title and author arguments. It creates a new Book object, stores it, and returns it.
Now test the mutation in the playground.
mutation {
addBook(title: "Learning GraphQL", author: "Alex Query") {
title
author
}
}
The mutation returns the newly added book. You can verify by running a query to list all books. You would need to add a new query field for that.
Integrating with a Database
For real applications, use a database. FastAPI works well with SQLAlchemy. You can follow a FastAPI SQLAlchemy CRUD Guide for details. Strawberry resolvers can be async. This fits perfectly with async database libraries.
Here is a conceptual example using an async function.
@strawberry.type
class Query:
@strawberry.field
async def get_books(self) -> list[Book]:
# Imagine this is an async database call
# async with session.execute(select(BookModel)) as result:
# books = result.scalars().all()
# return [Book(title=b.title, author=b.author) for b in books]
return books_db # Using our in-memory list for now
Using async allows your API to handle many concurrent requests. This is crucial for performance. FastAPI's async support makes this straightforward.
Error Handling and Validation
Strawberry and FastAPI provide good error handling. GraphQL errors are returned in a standard format. Input validation is automatic with type hints. For more complex validation, you can use Pydantic models. Learn more in the guide on FastAPI Validation with Pydantic Models.
If a resolver raises an exception, GraphQL will include it in the response. The client receives a clear error message. The rest of the query may still execute successfully.
Conclusion
Building GraphQL APIs with FastAPI and Strawberry is efficient. You get high performance from FastAPI. You get a type-safe schema from Strawberry. This combination is powerful for modern web development.
You learned to set up a project. You defined GraphQL types, queries, and mutations. You ran the server and tested queries in the playground. The next steps are adding a real database and authentication.
Consider exploring related topics. Learn how to Test FastAPI Endpoints with pytest and TestClient. Or learn to Deploy FastAPI with Docker for Production. These skills will help you build complete, production-ready applications.
Start building your own GraphQL API today. Experiment with different schemas and resolvers. The tools are ready and waiting for you.