Skip to main content

Distributed GraphQL with Apollo Server

Your apps will run faster if the APIs they call are physically located close to your end users. This tutorial will show you how to distribute an Apollo Server in multiple locations around the world by using the CloudFlow.

You'll first build a small Apollo Server container, push it to Docker Hub, and then deploy it to CloudFlow. This tutorial was inspired by an example from PreciousChicken.


Before starting, create a new CloudFlow Project and then delete the default Deployment and ingress-upstream Service to prepare the project for your new deployment.


  • You need an account on Docker Hub.
  • You need Docker and Node installed so that you can build a docker image.

Get Setup with Apollo

Install the relevant packages.

mkdir apollo
cd apollo
npm init -y
npm install apollo-server graphql

Create Your Container Image

The container image is Apollo code plus a small amount of static data, built upon node. For a real Apollo Server you'd have it pointing to a database or REST API. But static data is all we want for the minute. Let's start by saving the following code into index.js.

const { ApolloServer, gql } = require('apollo-server');

const data = {
"beasts": [
"id": "md",
"legs": 6,
"binomial": "Musca domestica",
"commonName": "housefly",
"id": "nr",
"legs": 8,
"binomial": "Neriene radiata",
"commonName": "filmy dome spider",
"id": "cc",
"legs": 2,
"binomial": "Corvus corone",
"commonName": "carrion crow",
"id": "fc",
"legs": 4,
"binomial": "Felis catus",
"commonName": "cat",

const typeDefs = gql`
type Beast {
id: ID
legs: Int
binomial: String
commonName: String

type Query {
beasts: [Beast]

const resolvers = {
Query: {
// Returns array of all beasts.
beasts: () => data.beasts

const server = new ApolloServer({ typeDefs, resolvers });

// The `listen` method launches a web server.
server.listen(4000).then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);

Now let's define the Dockerfile.

# Uses the node base image with the latest LTS version
FROM node:14.16.0
# Informs Docker that the container listens on the
# specified network ports at runtime
# Copies index.js and the two package files from the local
# directory to a new app directory on the container
COPY index.js package.json package-lock.json app/
# Changes working directory to the new directory just created
# Installs npm dependencies on container
RUN npm ci
# Command container will actually run when called
CMD ["node", "index.js"]

Build and Publish the Image

Build the Docker image and push it to Docker Hub, substituting YOUR_DOCKERHUB_ACCOUNT accordingly.

docker build -t my-apollo-server-image .
docker tag my-apollo-server-image YOUR_DOCKERHUB_ACCOUNT/my-apollo-server:latest
docker push YOUR_DOCKERHUB_ACCOUNT/my-apollo-server:latest

Create a Kubernetes Deployment for Apollo Server

Next, create a CloudFlow deployment for Apollo Server with a file apollo-deployment.yaml, substituting YOUR_DOCKERHUB_ACCOUNT accordingly. This will direct CloudFlow to distribute the container you've pushed to Docker Hub.

apiVersion: apps/v1
kind: Deployment
app: apollo
name: apollo
replicas: 1
app: apollo
app: apollo
- image: YOUR_DOCKERHUB_ACCOUNT/my-apollo-server:latest
imagePullPolicy: Always
name: apollo
memory: ".5Gi"
cpu: "500m"
memory: ".5Gi"
cpu: "500m"

Apply this deployment resource to your Project with either the Kubernetes dashboard or kubectl apply -f apollo-deployment.yaml.

Expose the Service on the Internet

We want to expose the Apollo Server on the Internet. Create ingress-upstream.yaml as defined below.

apiVersion: v1
kind: Service
app: ingress-upstream
name: ingress-upstream
- name: 80-80
port: 80
protocol: TCP
targetPort: 4000
app: apollo
sessionAffinity: None
type: ClusterIP

Apply this service resource to your Project with either the Kubernetes dashboard or kubectl apply -f ingress-upstream.yaml.

See the pods running on CloudFlow's network with kubectl get pods -o wide. The -o wide switch shows where your GraphQL API is running according to the default AEE location optimization strategy. Your GraphQL API will be optimally deployed according to traffic. In lieu of significant traffic, your deployment will be made to default locations.

Apollo pods

Try kubectl logs POD to see the log message reporting that the server is listening on port 4000.

Finally, follow the instructions that configure DNS and TLS.

Browse Your GraphQL API

Visit https://YOUR_ENVIRONMENT_HOSTNAME in your browser to play in the Apollo Sandbox. You may have multiple pods running in multiple locations, but your chosen hostname will route to the one that is physically closest.

Enter the following query:

beasts {

You'll see the following result:

Apollo Sandbox Beasts