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
- Create a new directory named
user-service
inside your project directory:
mkdir user-service
- Create a new file named
index.js
inside theuser-service
directory:
touch user-service/index.js
- 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
- Create a new directory named
post-service
inside your project directory:
mkdir post-service
- Create a new file named
index.js
inside thepost-service
directory:
touch post-service/index.js
- 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.
- Create a new directory named
gateway
inside your project directory:
mkdir gateway
- Create a new file named
index.js
inside thegateway
directory:
touch gateway/index.js
- 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.
- Open a new terminal and navigate to the
user-service
directory:
cd user-service
- Start the
user
service:
node index.js
- Open another terminal and navigate to the
post-service
directory:
cd post-service
- Start the
post
service:
node index.js
- Finally, open a third terminal and navigate to the
gateway
directory:
cd gateway
- 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.
No comments so far
Curious about this topic? Continue your journey with these coding courses: