# Strawberry GraphQL: a Python GraphQL library built on dataclasses

> Strawberry generates a GraphQL schema from Python type annotations, ships a dev server and a mypy plugin, and integrates with Django, FastAPI and other ASGI stacks. Here is what it does, how to start it, and where it stops being the right tool.

**strawberry-graphql/strawberry** — A GraphQL library for Python that leverages type annotations 🍓

- Repository: https://github.com/strawberry-graphql/strawberry
- Website: https://strawberry.rocks
- Stars: 4,722 · Forks: 664
- Language: Python
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/strawberry-graphql-strawberry

## The problem Strawberry solves for typed Python codebases

Most GraphQL servers in Python ask you to describe the schema twice: once in SDL or a schema builder, once in the resolver code that returns the data. Strawberry collapses that into one place. You decorate a class with @strawberry.type, annotate its fields, and the library reads those annotations to produce the schema. The README describes it as a "Python GraphQL library based on dataclasses", and that framing is accurate: the class body is the type definition.

The audience is narrow and specific. This is for teams that already run mypy or pyright, already use dataclasses or Pydantic models, and want the GraphQL layer to inherit that typing instead of sitting beside it. It is not aimed at people who want to write SDL by hand and generate Python stubs from it, and it is not a schema registry or a gateway. It is the layer that turns your Python types into an executable schema and serves it.

The pyproject.toml classifies the project as "Development Status :: 5 - Production/Stable" and requires Python >=3.10,<4.0. The core dependency set is small: graphql-core, typing-extensions, python-dateutil, packaging and cross-web. Everything framework-specific is an optional extra, so a plain install does not drag Django or FastAPI into your environment.

## How annotations become an executable GraphQL schema

The data flow is short enough to trace by hand. You define types and a Query class, then pass the query type to strawberry.Schema. That constructor walks the annotated fields, maps Python types to GraphQL types (str to String, int to Int, and so on), collects the resolvers from @strawberry.field decorated methods, and produces a schema object. The schema is what you hand to a view or a server adapter.

The README example makes the mapping concrete: a User type with name: str and age: int, a Query with a user field returning a hardcoded User, and a module-level schema = strawberry.Schema(query=Query). The field method is the resolver; its return annotation is the field type. There is no separate registration step.

Two design choices are worth naming. First, the mypy plugin: adding plugins = strawberry.ext.mypy_plugin to your mypy configuration makes the type checker aware of the generated schema, so mismatches between a resolver's declared return type and the GraphQL field it backs surface at check time rather than at query time. Second, the integrations are adapters rather than a framework of their own. The Django path is a view class you mount in urls.py; the ASGI extra pulls in starlette and python-multipart; there are separate extras for aiohttp, flask, quart, sanic, channels, fastapi, pydantic and apollo-federation. You pick the one that matches your deployment, and the core stays unchanged.

## Installing Strawberry GraphQL and serving a first schema

The README's quick start installs the CLI extra, which brings in the dev server and the strawberry command. Run it in a virtual environment:

```bash
pip install "strawberry-graphql[cli]"
```

Create app.py with a type, a query and a schema. The README uses exactly this shape:

```python
import strawberry


@strawberry.type
class User:
    name: str
    age: int


@strawberry.type
class Query:
    @strawberry.field
    def user(self) -> User:
        return User(name="Patrick", age=100)


schema = strawberry.Schema(query=Query)
```

Serve it with the dev server, pointing at the module name rather than the file path:

```bash
strawberry dev app
```

The README says the dev server is reachable at http://0.0.0.0:8000/graphql, which opens GraphiQL for testing queries. If you want the type checker to validate the schema against your annotations, add the plugin to mypy.ini:

```ini
[mypy]
plugins = strawberry.ext.mypy_plugin
```

For Django, the README gives two steps: add "strawberry.django" to INSTALLED_APPS, then mount the view.

```python
from strawberry.django.views import GraphQLView
from .schema import schema

urlpatterns = [
    ...,
    path("graphql", GraphQLView.as_view(schema=schema)),
]
```

That is the whole first-run path. Nothing in the README describes authentication, pagination or query depth limits, so treat those as things you add yourself.

## Where Strawberry is the wrong choice

The dataclass-first model has a real cost: the Python classes are the source of truth, so a schema-first team that wants the SDL reviewed and versioned independently will find the workflow inverted. You can export the schema, but the README does not document a round-trip that keeps a hand-edited SDL authoritative.

The optional-dependency split is also a maintenance surface. The Django extra pins Django>=5.2 and asgiref>=3.2; the fastapi extra pins fastapi>=0.65.2 and python-multipart; the asgi extra pins starlette>=0.18.0 and python-multipart>=0.0.7. Each of those pins is a place where a framework upgrade and a Strawberry upgrade can disagree, and the README does not document a compatibility matrix beyond the pins themselves.

Version churn is worth planning for. Releases 0.327.5, 0.327.6 and 0.327.7 all landed on 2026-09-07, three patch releases in a single day. That pattern is normal for a library with this many integrations, but it means an unpinned install can move under you between deploys. The repository's last push was on 2026-09-21, two days before this writing, so the project is being worked on, but the README does not document a deprecation policy or a rollback procedure for a bad release.

Finally, the README does not cover performance. There is no statement about query cost analysis, batching, or N+1 behaviour, and no benchmark is published in the README or pyproject.toml. If your workload is dominated by deeply nested queries over a relational database, you will be solving that problem with dataloaders or query planning that this documentation does not describe.

## How Strawberry differs from Ariadne and Graphene

The closest comparison is Ariadne, which takes the opposite approach: you write SDL as a string or a .graphql file, and Ariadne binds resolvers to the fields named in that SDL. The schema is the artifact you read and review; the Python code is glue. Strawberry inverts that. In Strawberry, the Python class is the artifact and the SDL is derived from it. If your team reviews schema changes in pull requests as SDL diffs, Ariadne matches that habit; if your team reviews Python type changes, Strawberry does.

Graphene is the older Python GraphQL library, and its model is class-based schema definition with explicit field classes rather than type annotations. The practical difference is what the type checker can see. Strawberry's mypy plugin is documented in the README as enabling static type-checking of the schema, which means a resolver returning the wrong type is a check-time error. With Graphene's explicit field objects, that class of mismatch is not caught by the same mechanism.

The honest summary: Strawberry is not better in the abstract, it is aligned with a different starting point. Teams that already treat annotations as the interface contract get less duplication. Teams that treat SDL as the contract get more.

## Maintenance, licensing and the cost of upgrading

The repository is not archived, and the last push was on 2026-09-21. Releases are frequent: the three most recent listed are 0.327.5, 0.327.6 and 0.327.7, all dated 2026-09-07. The version is still in the 0.327 range, which under semantic versioning conventions means the project has not declared a 1.0 stability boundary even though pyproject.toml carries the "Production/Stable" classifier. Both statements are in the repository, and they pull in different directions; the version number is the more conservative signal when you decide how tightly to pin.

Upgrade cost concentrates in the optional extras. Because Django, FastAPI, Starlette and the rest are pinned inside Strawberry's own optional-dependency table, a Strawberry bump can change the framework version your environment resolves to. Pinning Strawberry to an exact version and letting your own lockfile control the framework is the cheaper arrangement. The CHANGELOG.md at the repository root and the changelog link in pyproject.toml (https://strawberry.rocks/changelog) are where release notes live; the README itself does not describe an upgrade procedure.

Licensing is MIT, stated in both the README and pyproject.toml (license = "MIT", with license-files = ["LICENSE"]). MIT is permissive: it allows commercial and closed-source use, modification and redistribution, with the licence and copyright notice retained. That is a description of the licence text, not legal advice; if your organisation has a policy on dependency licences, run it through that process. The README also asks that sensitive security bugs go to patrick.arminio@gmail.com rather than the public issue tracker, which is a coordination detail worth knowing before you file anything.

## Conclusion

Adopt Strawberry if your team already writes typed Python and wants the schema to follow the annotations rather than a separate SDL file, and if Django, FastAPI or Starlette is already in the stack. Do not adopt it if you need a schema-first workflow where the SDL is the source of truth, or if you are on Python below 3.10, since pyproject.toml requires >=3.10,<4.0. Before committing, verify three things: that the mypy plugin runs cleanly against your existing code, that the version you pin is the one whose changelog you have read, and that your server integration (strawberry.django, or the ASGI extra) matches the framework you actually deploy.

## FAQ

### How do I install Strawberry GraphQL with the dev server?

The README's quick start installs the CLI extra with pip install "strawberry-graphql[cli]", which provides the strawberry command and the dev server. You then run strawberry dev app against a module containing a schema.

### Does Strawberry GraphQL work with Django?

Yes. The README documents adding "strawberry.django" to INSTALLED_APPS and mounting GraphQLView.as_view(schema=schema) in urls.py. The django extra pins Django>=5.2 and asgiref>=3.2.

### What Python version does Strawberry GraphQL require?

pyproject.toml sets requires-python to >=3.10,<4.0, so Python 3.10 or newer is required and Python 4 is excluded.

### What licence is Strawberry GraphQL released under?

MIT. Both the README and pyproject.toml state it, with license-files pointing at the LICENSE file in the repository root.

### Can Strawberry GraphQL type-check my schema with mypy?

The README documents a mypy plugin enabled by adding plugins = strawberry.ext.mypy_plugin under [mypy] in mypy.ini, which enables statically type-checking your GraphQL schema.

## Sources

- [License: MIT](https://github.com/strawberry-graphql/strawberry/blob/main/LICENSE)
- [Project website](https://strawberry.rocks)
- [README](https://github.com/strawberry-graphql/strawberry/blob/main/README.md)
- [Releases](https://github.com/strawberry-graphql/strawberry/releases)
- [strawberry-graphql/strawberry on GitHub](https://github.com/strawberry-graphql/strawberry)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/strawberry-graphql-strawberry
