GraphQL API with Rust: Step-by-Step Practical Tutorial

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Rust and GraphQL Are the Perfect Pair

\n

Modern web development demands high performance and strict typing. Rust, known for its memory safety and speed, is an excellent choice for building backends. GraphQL, in turn, provides a flexible and efficient way to work with data. In this tutorial, we will build a full-fledged GraphQL API in Rust using the async-graphql library and the actix-web framework. You will learn how to define schemas, write resolvers, and handle queries.

\n

By the end of the article, you will have a working server ready for integration into real projects. All code examples are tested and ready to run.

\n\n

Project Setup and Dependency Installation

\n

First, let's create a new Rust project. Make sure you have Rust installed (version 1.75+ is recommended).

\n
cargo new graphql-rust-api\ncd graphql-rust-api
\n

Open Cargo.toml and add the following dependencies:

\n
[dependencies]\nactix-web = "4"\nactix-rt = "2"\nasync-graphql = "7"\nasync-graphql-actix-web = "7"\nserde = { version = "1", features = ["derive"] }\ntokio = { version = "1", features = ["macros"] }
\n

Run cargo build to download and compile all dependencies. This may take a few minutes on the first run.

\n\n

Project Structure

\n

Create the following folder and file structure:

\n
src/\n├── main.rs\n├── schema.rs\n├── models.rs\n└── resolvers.rs
\n

We will fill each file step by step.

\n\n

Defining Models and GraphQL Schema

\n

Let's start by creating a simple data model. In models.rs, we'll describe the User structure:

\n
use serde::{Deserialize, Serialize};\n\n#[derive(Debug, Clone, Serialize, Deserialize)]\npub struct User {\n    pub id: u32,\n    pub name: String,\n    pub email: String,\n}
\n

Now let's move to schema.rs. Here we will define GraphQL objects and queries:

\n
use async_graphql::{Context, Object, SimpleObject};\nuse crate::models::User;\nuse crate::resolvers::get_all_users;\n\n#[derive(SimpleObject)]\npub struct UserObject {\n    pub id: u32,\n    pub name: String,\n    pub email: String,\n}\n\npub struct QueryRoot;\n\n#[Object]\nimpl QueryRoot {\n    async fn users(&self, ctx: &Context<'_>) -> Vec<UserObject> {\n        let users = get_all_users(ctx).await;\n        users.into_iter().map(|u| UserObject {\n            id: u.id,\n            name: u.name,\n            email: u.email,\n        }).collect()\n    }\n}
\n

Note the use of #[derive(SimpleObject)] — this is an async-graphql macro that automatically generates a GraphQL type.

\n\n

Resolvers: Business Logic

\n

In the resolvers.rs file, we'll implement the data retrieval function. For simplicity, we'll use a static list:

\n
use async_graphql::Context;\nuse crate::models::User;\n\npub async fn get_all_users(_ctx: &Context<'_>) -> Vec<User> {\n    vec![\n        User { id: 1, name: "Alice".into(), email: "alice@example.com".into() },\n        User { id: 2, name: "Bob".into(), email: "bob@example.com".into() },\n        User { id: 3, name: "Charlie".into(), email: "charlie@example.com".into() },\n    ]\n}
\n

In a real project, this could involve a database query or an external API call.

\n\n

Building the Server with Actix-web

\n

Now for the main part — let's put everything together in main.rs:

\n
use actix_web::{web, App, HttpServer, HttpResponse};\nuse async_graphql::{Schema, EmptyMutation, EmptySubscription};\nuse async_graphql_actix_web::{GraphQLRequest, GraphQLResponse};\nuse crate::schema::QueryRoot;\n\nmod models;\nmod schema;\nmod resolvers;\n\ntype AppSchema = Schema<QueryRoot, EmptyMutation, EmptySubscription>;\n\nasync fn graphql_handler(\n    schema                

Blogs

Book Recommendations