GraphQL in Rust
Expose flexible queries with async-graphql and Axum - schemas, resolvers, and DataLoader for N+1 prevention.
Busca en todas las páginas de la documentación
Expose flexible queries with async-graphql and Axum - schemas, resolvers, and DataLoader for N+1 prevention.
Quick-reference recipe card - copy-paste ready.
use async_graphql::{Context, Object, Schema, SimpleObject};
#[derive(SimpleObject)]
struct User { id: i64, name: String }
struct Query;
#[Object]
impl Query {
async fn user(&self, ctx: &Context<'_>, id: i64) -> async_graphql::Result<User> {
Ok(User { id, name: "Ada".into() })
}
}
type AppSchema = Schema<Query, async_graphql::EmptyMutation, async_graphql::EmptySubscription>;When to reach for this: Clients need flexible field selection and nested graphs - mobile apps, BFFs, or admin explorers.
use async_graphql::{Context, Object, Schema, SimpleObject};
use async_graphql_axum::{GraphQLRequest, GraphQLResponse};
use axum::{routing::post, Router};
#[derive(SimpleObject, Clone)]
struct User { id: i64, name: String }
#[derive(Clone)]
struct AppState { users: Vec<User> }
struct Query;
#[Object]
impl Query {
async fn users(&self, ctx: &Context<'_>) -> Vec<User> {
ctx.data_unchecked::<AppState>().users.clone()
}
}
type AppSchema = Schema<Query, async_graphql::EmptyMutation, async_graphql::EmptySubscription>;
async fn graphql_handler(
schema: axum::Extension<AppSchema>,
req: GraphQLRequest,
) -> GraphQLResponse {
schema.0.execute(req.into_inner()).await.into()
}
#[tokio::main]
async fn main() {
let state = AppState { users: vec![User { id: 1, name: "Ada".into() }] };
let schema = Schema::build(Query, async_graphql::EmptyMutation, async_graphql::EmptySubscription)
.data(state)
.finish();
let app = Router::new()
.route("/graphql", post(graphql_handler))
.layer(axum::Extension(schema));
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}What this demonstrates:
#[Object] impl defines Query root resolvers.SimpleObject for output types..data(state) for resolver context.async_graphql_axum integrates with Axum POST handler./graphql endpoint accepts query document + variables JSON.| Topic | GraphQL | REST |
|---|---|---|
| Over-fetching | Client picks fields | Fixed response DTO |
| Versioning | Evolve schema carefully | URL /v1 |
| Caching | Harder at HTTP layer | GET cache friendly |
| Complexity | Query depth/cost limits needed | Simpler ops |
// DataLoader for batched DB fetch
// use async_graphql::dataloader::Loaderlimit_depth and complexity analysis.errors array. Fix: Map to safe extensions only.| Alternative | Use When | Don't Use When |
|---|---|---|
| REST + OpenAPI | Public simple CRUD | Highly variable client field needs |
| gRPC | Service mesh internal | Browser clients |
juniper | Older Juniper ecosystem | New projects - async-graphql default |
WebSocket transport with async-graphql subscription root.
GraphQL multipart spec support in async-graphql.
Extract bearer token in Axum middleware; insert AuthUser in schema data.
APQ for mobile clients to reduce payload size.
async-graphql exports schema SDL for frontend codegen.
Query complexity score * cost budget per IP.
schema.execute(Request::new(query)).await in unit tests.
Same Axum router - /graphql and /v1/* routes.
Pass PgPool in schema data; resolvers use sqlx directly.
Simple CRUD with few clients - REST is less operational burden.
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.
Revisado por Chris St. John·Última actualización: 19 jul 2026