Using GraphQL and Apollo Federation to Build Microservices

In recent years, microservices architecture has gained immense popularity among developers for its scalability, flexibility, and modularity. One of the challenges with microservices is how to manage communication between them, and GraphQL has emerged as an effective solution. Apollo Federation, a set of tools built on top of GraphQL, further simplifies the process of building and managing microservices. In this blog post, we'll walk you through using GraphQL and Apollo Federation to build microservices, step by step, with code examples and explanations tailored for beginners.

What are GraphQL and Apollo Federation?

Before diving into the process of building microservices, it's essential to understand what GraphQL and Apollo Federation are and their roles in microservices architecture.

GraphQL

GraphQL is a query language for APIs and a runtime for executing those queries against your data. Unlike REST, GraphQL allows clients to request only the data they need, reducing the amount of data sent over the network. It also enables you to evolve your API without versioning, which makes managing your API much more straightforward.

Apollo Federation

Apollo Federation is a set of tools and libraries built on top of GraphQL that allows you to create a single, unified GraphQL API by composing multiple, separately deployed GraphQL services. It simplifies the process of building and managing a microservices architecture by providing a declarative way to describe the relationships between your services and the data they expose.

Setting up the Environment

Before we start building our microservices, we need to set up the development environment. For this tutorial, we'll use Node.js, so make sure you have it installed on your system. You can download Node.js from the official website.

Creating a New Project

First, create a new directory for your project and navigate to it:

mkdir graphql-apollo-federation-microservices cd graphql-apollo-federation-microservices

Next, run the following command to initialize a new Node.js project:

npm init -y

This command creates a package.json file with default values.

Installing Dependencies

We'll need to install some dependencies for this project. Run the following command to install them:

npm install apollo-server graphql apollo-federation

Building Microservices with GraphQL and Apollo Federation

In this section, we'll create two simple microservices using GraphQL and Apollo Federation: a user service and a post service.

Creating the User Service

  1. Create a new directory named user-service inside your project directory:
mkdir user-service
  1. Create a new file named index.js inside the user-service directory:
touch user-service/index.js
  1. Open index.js in your favorite code editor and add the following code:
const { ApolloServer, gql } = require('apollo-server'); const { buildFederatedSchema } = require('@apollo/federation'); // Sample data const users = [ { id: 1, name: 'Alice', age: 30 }, { id: 2, name: 'Bob', age: 28 }, { id: 3, name: 'Charlie', age: 22 }, ]; // GraphQL schema const typeDefs = gql` type User @key(fields: "id") { id: ID! name: String! age: Int! } type Query { getUser(id: ID!): User allUsers: [User] } `; // Resolvers const resolvers = { Query: { getUser: (_, { id }) => users.find(user => user.id === parseInt(id)), allUsers: ()```javascript allUsers: () => users, }, User: { __resolveReference(user, { id }) { return users.find(existingUser => existingUser.id === parseInt(id)); }, }, }; // Apollo server setup const server = new ApolloServer({ schema: buildFederatedSchema([{ typeDefs, resolvers }]), }); // Start server server.listen({ port: 4001 }).then(({ url }) => { console.log(`User service running at ${url}`); });

This code sets up a simple GraphQL server for the user service using Apollo Server and Apollo Federation. We have sample data for users, a GraphQL schema defining the User type, and resolvers for our queries. The server listens on port 4001.

Creating the Post Service

  1. Create a new directory named post-service inside your project directory:
mkdir post-service
  1. Create a new file named index.js inside the post-service directory:
touch post-service/index.js
  1. Open index.js in your favorite code editor and add the following code:
const { ApolloServer, gql } = require('apollo-server'); const { buildFederatedSchema } = require('@apollo/federation'); // Sample data const posts = [ { id: 1, title: 'First Post', content: 'This is the first post.', authorId: 1 }, { id: 2, title: 'Second Post', content: 'This is the second post.', authorId: 2 }, { id: 3, title: 'Third Post', content: 'This is the third post.', authorId: 1 }, ]; // GraphQL schema const typeDefs = gql` type Post @key(fields: "id") { id: ID! title: String! content: String! author: User! } extend type User @key(fields: "id") { id: ID! @external posts: [Post] } type Query { getPost(id: ID!): Post allPosts: [Post] } `; // Resolvers const resolvers = { Query: { getPost: (_, { id }) => posts.find(post => post.id === parseInt(id)), allPosts: () => posts, }, Post: { author(post) { return { __typename: 'User', id: post.authorId }; }, }, User: { posts(user) { return posts.filter(post => post.authorId === parseInt(user.id)); }, }, }; // Apollo server setup const server = new ApolloServer({ schema: buildFederatedSchema([{ typeDefs, resolvers }]), }); // Start server server.listen({ port: 4002 }).then(({ url }) => { console.log(`Post service running at ${url}`); });

This code sets up a simple GraphQL server for the post service. We have sample data for posts, a GraphQL schema defining the Post type, and resolvers for our queries. The server listens on port 4002.

Connecting Microservices with Apollo Gateway

Now that we have our microservices set up, we need to connect them using Apollo Gateway.

  1. Create a new directory named gateway inside your project directory:
mkdir gateway
  1. Create a new file named index.js inside the gateway directory:
touch gateway/index.js
  1. Open index.js in your favorite code editor and add the following code:
```javascript const { ApolloServer } = require('apollo-server'); const { ApolloGateway } = require('@apollo/gateway'); // Apollo Gateway setup const gateway = new ApolloGateway({ serviceList: [ { name: 'user', url: 'http://localhost:4001' }, { name: 'post', url: 'http://localhost:4002' }, ], }); // Apollo server setup const server = new ApolloServer({ gateway, subscriptions: false, }); // Start server server.listen({ port: 4000 }).then(({ url }) => { console.log(`Gateway running at ${url}`); });

This code sets up an Apollo Gateway that connects our user and post services. The gateway listens on port 4000.

Running the Application

To run the application, you need to start each service and the gateway separately.

  1. Open a new terminal and navigate to the user-service directory:
cd user-service
  1. Start the user service:
node index.js
  1. Open another terminal and navigate to the post-service directory:
cd post-service
  1. Start the post service:
node index.js
  1. Finally, open a third terminal and navigate to the gateway directory:
cd gateway
  1. Start the gateway:
node index.js

Now you can use GraphQL Playground or another GraphQL client to interact with your unified GraphQL API at http://localhost:4000.

FAQ

Q: What is the difference between GraphQL and REST?

A: GraphQL is a query language for APIs that allows clients to request only the data they need, whereas REST is an architectural style that defines a set of constraints for building web services. GraphQL can provide more efficient data retrieval and simplify API versioning compared to REST.

Q: What is the role of Apollo Gateway in the context of microservices?

A: Apollo Gateway acts as a central entry point for clients to interact with your microservices. It connects and composes the GraphQL schemas of each microservice into a single, unified GraphQL schema, allowing clients to request data from multiple services with a single query.

Q: Can I use Apollo Federation with other languages besides JavaScript?

A: Yes, Apollo Federation is designed to work with any language that supports GraphQL. There are Apollo Federation libraries available for other languages, such as Python, Ruby, and Java.

Q: How can I secure my microservices built with GraphQL and Apollo Federation?

A: You can use authentication and authorization mechanisms like JWT (JSON Web Tokens), OAuth 2.0, or custom middleware to secure your microservices. Apollo Server also provides built-in support for persisted queries, which can help prevent denial-of-service (DoS) attacks.

Sharing is caring

Did you like what Mehul Mohan wrote? Thank them for their work by sharing it on social media.

0/10000

No comments so far