Skip to content

bhupendra05/graphql-fastapi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GraphQL API with FastAPI + Strawberry

A production-ready GraphQL API built with FastAPI and Strawberry (code-first), backed by SQLAlchemy + SQLite. Includes N+1 prevention via eager loading, full CRUD mutations with input validation, and an interactive GraphQL Playground.

Setup

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python main.py
# API at http://localhost:8000
# GraphQL Playground at http://localhost:8000/graphql

Example Queries

Get all users with their posts

query {
  users {
    id
    username
    email
    posts {
      id
      title
      createdAt
    }
  }
}

Get a single post

query {
  post(id: 1) {
    id
    title
    content
    author {
      username
      email
    }
  }
}

Paginated posts

query {
  posts(limit: 5, offset: 0) {
    id
    title
    author { username }
  }
}

Example Mutations

Create a user

mutation {
  createUser(input: { username: "carol", email: "carol@example.com" }) {
    id
    username
    email
  }
}

Create a post

mutation {
  createPost(input: {
    title: "My First Post"
    content: "Hello GraphQL world!"
    authorId: 1
  }) {
    id
    title
    createdAt
    author { username }
  }
}

Update a user

mutation {
  updateUser(id: 1, input: { email: "newemail@example.com" }) {
    id
    username
    email
  }
}

Delete a post

mutation {
  deletePost(id: 2) {
    success
    message
  }
}

Architecture

graphql-fastapi/
├── main.py          # FastAPI app + GraphQL router + startup seed
├── db/
│   ├── __init__.py  # Engine, session, get_db dependency
│   └── models.py    # SQLAlchemy ORM models (User, Post)
└── schema/
    ├── types.py     # Strawberry types and input types
    ├── queries.py   # Query resolvers (eager loading for N+1 prevention)
    └── mutations.py # Create/update/delete resolvers with validation

N+1 Prevention

Without optimization, fetching 100 users with their posts would make 101 queries. This is prevented with SQLAlchemy's joinedload:

# BAD: N+1 — one query per user to load posts
users = db.query(User).all()
for user in users:
    posts = user.posts  # triggers a new query for each user

# GOOD: 2 queries total (1 for users, 1 join for posts)
from sqlalchemy.orm import joinedload
users = db.query(User).options(joinedload(User.posts)).all()

Switching to PostgreSQL

Change the database URL in db/__init__.py:

DATABASE_URL = "postgresql://user:password@localhost/dbname"

And install the driver:

pip install psycopg2-binary

About

GraphQL API with FastAPI + Strawberry (code-first) — full CRUD, N+1 prevention, interactive playground

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages