Building an Apollo Federation API with Rust: A JavaScript Developer’s Perspective

This tutorial walks a JavaScript‑savvy developer through creating a Rust‑based Apollo Federation GraphQL API, covering project setup with Cargo, required dependencies, async main function, schema and type definitions, federation extensions, and how to run the user and dog sub‑services on separate ports.

Code DAO
Code DAO
Code DAO
Building an Apollo Federation API with Rust: A JavaScript Developer’s Perspective

In this guide we build a federated GraphQL API using Rust, targeting developers familiar with JavaScript. The API consists of two subgraphs – a user service and a dog service – where the dog subgraph extends the user type.

Setup

First create a new directory for the API and two Cargo projects for the subgraphs:

mkdir dogs-api
cd dogs-api
cargo new users
cargo new dogs

Edit each subgraph’s Cargo.toml to add the following dependencies:

[dependencies]
 tokio = { version = "1.0.2", features = ["macros", "rt-multi-thread"] }
 warp = "0.3"
 http = "0.2"
 async-graphql = "3.0.34"
 async-graphql-warp = "3.0.34"

tokio provides the async runtime for async/await support.

warp is the HTTP server handling inbound and outbound requests.

http supplies type definitions used throughout the code.

async-graphql and async-graphql-warp process GraphQL queries and mutations.

Async Main Function

Because the server needs asynchronous handling, we annotate the entry point with #[tokio::main] and define an async main function:

#[tokio::main]
async fn main() {
    println!("hello world");
}

Module Declarations

We import the necessary types from the async‑graphql and warp crates:

use async_graphql::{http::{playground_source, GraphQLPlaygroundConfig}, EmptyMutation, EmptySubscription, Object, Schema, SimpleObject};
use async_graphql_warp::{GraphQLBadRequest, GraphQLResponse};
use http::StatusCode;
use std::convert::Infallible;
use warp::{http::Response as HttpResponse, Filter, Rejection};

Server Creation – Comparison with Apollo Server Express

In Node, an Apollo Federation server is built by creating an Express app, initializing ApolloServer, applying it as middleware, and then starting the Express listener. The Rust version follows the same logical steps but uses warp routes and async‑graphql instead of Express and Apollo Server.

// Node example
const app = express();
const startServer = async () => {
  const apolloServer = new ApolloServer({ schema });
  await apolloServer.start();
  apolloServer.applyMiddleware({ app });
};
startServer();
app.listen(port, () => console.log(`Service ready at port ${port}!`));

In Rust we define a GraphQL post handler, a Playground route, combine them, and serve with warp:

#[tokio::main]
async fn main() {
    // 1. Define variable to handle incoming GraphQL posts
    let graphql_post = async_graphql_warp::graphql(schema).and_then(
        |(schema, request): (Schema<Query, EmptyMutation, EmptySubscription>, async_graphql::Request)| async move {
            Ok::<_, Infallible>(GraphQLResponse::from(schema.execute(request).await))
        },
    );
    // Bonus – Playground route
    let graphql_playground = warp::path::end().and(warp::get()).map(|| {
        HttpResponse::builder()
            .header("content-type", "text/html")
            .body(playground_source(GraphQLPlaygroundConfig::new("/")))
    });
    // 2. Apply variables as routes
    let routes = graphql_playground.or(graphql_post).recover(|err: Rejection| async move {
        if let Some(GraphQLBadRequest(err)) = err.find() {
            return Ok(warp::reply::with_status(err.to_string(), StatusCode::BAD_REQUEST));
        }
        Ok(warp::reply::with_status("INTERNAL_SERVER_ERROR".to_string(), StatusCode::INTERNAL_SERVER_ERROR))
    });
    // 3. Start the server (customize the port as needed)
    warp::serve(routes).run(([0, 0, 0, 0], 5011)).await;
}

Schema, TypeDefs, and Resolvers

We build the schema at the top of main:

let schema = Schema::build(Query, EmptyMutation, EmptySubscription).finish();

Type definitions in Rust mirror the GraphQL SDL. For example, the User type:

#[derive(SimpleObject)]
struct User {
    name: String,
    id: i32,
}

And the Dog type with an owner reference:

#[derive(SimpleObject)]
struct Dog {
    color: String,
    name: String,
    age: i32,
    id: i32,
    owner: User,
}

Federation extensions use the #[Object(extends)] macro and the #[graphql(external)] attribute to mark fields that are provided by another subgraph. The dog subgraph extends User with a @key on id and adds a dogs field.

// Rust – extending User
#[Object(extends)]
impl User {
    #[graphql(external)]
    async fn id(&self) -> &i32 { &self.id }
    async fn dogs(&self) -> Vec<Dog> {
        // Find and return vector of dogs
    }
}

Entity resolvers are defined on the query type using #[graphql(entity)]:

#[Object(extends)]
impl Query {
    #[graphql(entity)]
    async fn resolve_user(&self, id: i32) -> User { User { id } }
    async fn get_user(&self) -> User { User { name: "Nick".to_string(), id: 1 } }
    async fn get_dog(&self) -> Dog { /* return a Dog instance */ }
}

Running the Subgraphs

Each subgraph is started with cargo run on a distinct port (e.g., 5010 for dogs and 5011 for users). The console prints the Playground URL so you can test queries against each service.

With both services running, Apollo Federation can compose the overall schema, allowing queries that span users and their dogs.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

backendrusttutorialGraphQLwarpapollo federationasync-graphql
Code DAO
Written by

Code DAO

We deliver AI algorithm tutorials and the latest news, curated by a team of researchers from Peking University, Shanghai Jiao Tong University, Central South University, and leading AI companies such as Huawei, Kuaishou, and SenseTime. Join us in the AI alchemy—making life better!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.