Library / SDK
mirumee/ariadne avatar
mirumee/ariadne

mirumee/ariadne: a schema-first GraphQL library for Python

Python library for implementing GraphQL servers using schema-first approach. Created with :heart: by Mirumee

2,344 stars197 forksPythonBSD-3-Clause

At a glance

What is it?
Ariadne builds GraphQL servers in Python by binding resolver functions to an SDL schema rather than deriving the schema from code. It integrates with Django, FastAPI, Flask and Starlette, requires Python 3.10 or higher, and ships optional support for SQLAlchemy 2.0 and Apollo Federation.
Who is it for?
Ariadne suits teams that maintain a shared SDL schema as the API contract between frontend and backend. Its ASGI and WSGI adapters cover Django, FastAPI, Flask and Starlette, and the SQLAlchemy 2.0 integration removes boilerplate resolvers for database-backed fields.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Schema-first versus code-first: what Ariadne commits you to

Schema-first means the SDL schema is the source of truth for both sides of the API. Ariadne targets teams that define the API contract in SDL and share that file with client teams, who use tools like graphql-code-generator or Apollo Client code generation to produce typed queries from it. Both tools start from the SDL, so a schema-first server fits without any conversion layer.

Code-first libraries like Strawberry and Graphene take the opposite position: the Python class definition is the source and SDL is generated from it. With code-first, adding a field means adding a Python annotation; with Ariadne, it means updating the SDL and writing a corresponding resolver. Teams with existing Pydantic or dataclass models may find that cost immediate. Ariadne makes sense when the schema is designed as a shared contract, not derived from the implementation.

How gql(), QueryType and make_executable_schema assemble a running schema

Three components form Ariadne's binding model. gql() wraps an SDL string and runs a GraphQL syntax parse at import time, raising GraphQLSyntaxError before the first HTTP request if the schema contains a syntax error. gql() validates syntax only; it does not check that Python resolver functions exist for every field.

QueryType and ObjectType map Python functions to GraphQL fields by name. Ariadne keeps all state local to each schema instance, with no global registry and no singleton, which is what lets multiple GraphQL APIs run in the same Python process by creating independent QueryType, ObjectType and make_executable_schema() instances.

make_executable_schema() accepts an SDL string (or a list of strings, or files loaded from .graphql, .gql and .graphqls extensions) alongside the bound types and returns a runnable schema. Passing the schema to GraphQL(schema) produces the ASGI app.

Installing Ariadne and binding the first resolvers

Ariadne installs from PyPI:

bash
pip install ariadne

Python 3.10 or higher (up to 3.14) is required. For a local development server, install uvicorn:

bash
pip install uvicorn

The quickstart pattern in the README defines an SDL schema string, passes it to gql(), then uses QueryType and ObjectType to attach resolvers before calling make_executable_schema():

python
query = QueryType()
person = ObjectType("Person")

@query.field("people")
def resolve_people(*_):
    return [
        {"firstName": "John", "lastName": "Doe", "age": 21},
        {"firstName": "Bob", "lastName": "Boberson", "age": 24},
    ]

@person.field("fullName")
def resolve_person_fullname(person, *_):
    return "%s %s" % (person["firstName"], person["lastName"])

schema = make_executable_schema(type_defs, query, person)
app = GraphQL(schema, debug=True)

Start the server with `uvicorn example:app` and a built-in GraphiQL explorer is available at http://127.0.0.1:8000.

ASGI and WSGI adapters: Django, FastAPI, Flask and Starlette

ariadne.asgi.GraphQL is an ASGI application that handles HTTP for queries and mutations and WebSocket connections for subscriptions. Mount it under FastAPI with app.mount() or integrate it into Django Channels routing as an ASGI consumer; both frameworks use Starlette internally, so the adapter works across the ASGI stack without framework-specific code inside the resolvers.

For synchronous Flask applications and other WSGI servers, Ariadne ships a separate WSGI handler. File upload support requires the python-multipart package, listed under the asgi-file-uploads optional dependency group in pyproject.toml.

Example files in the repository cover FastAPI (examples/fastapi_integration_example.py) and Flask (examples/flask_integration_example.py). Subscription examples cover both async generators (examples/async_subscription_example.py) and the GraphQL-WS protocol (examples/graphql_ws_subscription_example.py).

The opt-in camelCase-to-snake_case mapping and the SQLAlchemy 2.0 integration

GraphQL field names follow camelCase by convention while Python attribute names follow snake_case, and without Ariadne's opt-in mapping, a field named createdAt in the SDL needs an explicit resolver that reads obj.created_at from Python. With the mapping enabled, Ariadne handles camelCase123-to-snake_case_123 translation automatically, including trailing digit segments.

Ariadne also ships automated integration with SQLAlchemy 2.0 for zero-boilerplate resolvers and N+1 prevention. The examples/ directory contains a sqlalchemy/ folder with usage patterns. The "2.0" in the feature description is specific: the integration targets SQLAlchemy 2.0 and is not described as covering SQLAlchemy 1.x. Projects still on SQLAlchemy 1.x would need to write resolvers by hand.

Subscriptions, Apollo Federation and the Starlette version ceiling in pyproject.toml

Subscriptions work through async generators, sync generators and customizable subscription handlers. Apollo Federation is supported, allowing an Ariadne server to act as a subgraph in a federated schema. An OpenTelemetry extension handles tracing for queries and resolvers.

Reading pyproject.toml reveals a constraint the README does not mention: Ariadne pins its Starlette dependency to starlette>0.17,<2.0. Starlette is the HTTP layer underneath both the FastAPI and Django Channels integrations. The upper bound of <2.0 means that a Starlette 2.0 release would block installation until Ariadne ships a compatibility update. Projects that also depend directly on FastAPI should verify that both packages resolve to a compatible Starlette version before adding Ariadne.

Where schema-first becomes a liability: duplication and missing static checks

Maintaining both SDL and Python introduces two failure modes. First, a field added to the SDL without a corresponding resolver raises a runtime error on the first query that requests it, not at schema construction time, and no static analysis tool can verify resolver completeness because the binding is done at runtime through decorator registration. Second, if the project already has Pydantic models, SQLModel tables or dataclasses defining its types, those types must also be written in SDL. Every field rename then requires changes in two places.

Code-first libraries remove the duplication by deriving SDL from Python type annotations. Strawberry uses Python dataclasses with Strawberry decorators and integrates with the same ASGI framework stack, so migrating from Ariadne to Strawberry does not require replacing the framework layer. Graphene uses its own ObjectType class with a longer history in the Python GraphQL ecosystem. Both are viable alternatives when the Python type definitions are already the authoritative source and schema-sharing with frontend tooling is not a requirement.

Editorial conclusion

Ariadne suits teams that maintain a shared SDL schema as the API contract between frontend and backend. Its ASGI and WSGI adapters cover Django, FastAPI, Flask and Starlette, and the SQLAlchemy 2.0 integration removes boilerplate resolvers for database-backed fields. Teams with Pydantic or dataclass models will find the SDL duplication expensive; a code-first library like Strawberry removes that cost. Before adopting Ariadne, verify that your existing Starlette install falls below <2.0 as required in pyproject.toml. Ariadne uses the BSD-3-Clause licence; the last push to the repository was on 2026-08-31.

Frequently asked questions

What is mirumee/ariadne?

Ariadne is a Python library for building GraphQL servers using the schema-first approach. You define the API in SDL first and attach Python resolver functions to each field using QueryType and ObjectType decorators, which lets the SDL serve as a shared contract between the backend and any frontend code-generation toolchain. It supports ASGI and WSGI and integrates with Django, FastAPI, Flask and Starlette.

How do I install ariadne?

Run pip install ariadne. Python 3.10 or higher (up to 3.14) is required. For a local ASGI development server, install uvicorn separately with pip install uvicorn.

Does ariadne support subscriptions?

Yes. Ariadne supports subscriptions through async generators, sync generators and customizable subscription handlers. The repository includes examples for both approaches.

What is the difference between ariadne and Strawberry for Python GraphQL?

Ariadne uses a schema-first approach: you write SDL first and attach Python resolvers. Strawberry derives the SDL from Python dataclasses annotated with its decorators, making Python the single source of truth. Ariadne suits workflows that share the SDL with frontend code-generation tools; Strawberry suits projects that prefer to avoid maintaining a separate SDL file.

Does ariadne support Django?

Yes. Ariadne integrates with Django through both the ASGI path (Django Channels) and the WSGI path, using the corresponding GraphQL app class from ariadne.asgi or the WSGI handler.

Official sources

  1. License: BSD-3-Clause
  2. mirumee/ariadne on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mirumee-ariadne.svg)](https://hysenlabs.com/projects/mirumee-ariadne)