Skip to main content

Using Klotho with GraphQL Yoga and Express


This tutorial shows how to leverage Klotho's existing support for Express to create a cloud-ready GraphQL application using GraphQL Yoga.

Getting Started



Clone our sample apps git repo and install the npm packages for the ts-graphql-yoga app.

git clone
cd sample-apps/ts-graphql-yoga
npm install

Application Overview

The GraphQL Yoga sample application is an Express app that exposes a GraphQL Yoga server on its /graphql route. The server's schema includes a single query, hello, that returns "Hello from Klotho!" when executed.

This application utilizes the following annotations:

Wiring the Application for Compilation with Klotho

To wire the GraphQL Yoga application for compilation with Klotho, first a GraphQL Yoga server, graphQLServer, is created.

import { createServer } from "@graphql-yoga/node";

const graphQLServer = createServer({
schema: {
... // the schema is included in the complete sample application

Then an Express app is created and graphQLServer is mounted as a route handler on its /graphql route.

import * as express from "express";

const app = express();

app.use('/graphql', graphQLServer)

Finally, the application listens for requests to the Express app with an invocation of app.listen annotated with @kotho::expose.

/* @klotho::expose {
* target = "public"
* id = "graphql-yoga-gateway"
* }
app.listen(3000, async () => {
'Running GraphQL Yoga API Server at http://localhost:3000/graphql'

Compiling the Application with Klotho

Start by compiling the typescript application into javascript.

npx tsc

The compiled output will be located in the ./dist directory.

Then compile the application with Klotho.

klotho . --app ts-graphql-yoga --provider aws
██╗  ██╗██╗      ██████╗ ████████╗██╗  ██╗ ██████╗
██║ ██╔╝██║ ██╔═══██╗╚══██╔══╝██║ ██║██╔═══██╗
█████╔╝ ██║ ██║ ██║ ██║ ███████║██║ ██║
██╔═██╗ ██║ ██║ ██║ ██║ ██╔══██║██║ ██║
██║ ██╗███████╗╚██████╔╝ ██║ ██║ ██║╚██████╔╝
╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝

Adding resource input_file_dependencies:
Adding resource exec_unit:main
index.js: Adding in catchall route for prefix '/graphql' for middleware 'graphQLServer'
Found 2 route(s) for middleware 'graphQLServer'
Adding resource gateway:graphql-yoga-gateway
Adding resource topology:ts-graphql-yoga
Adding resource infra_as_code:Pulumi (AWS)

In the ./compiled folder, you will find the Infrastructure-as-Code (IaC) for your cloud-native application ready for deployment. You will also find a file called ts-graphql-yoga.png, visualizing the topology output of your compiled application:

topology diagram showing an API Gateway targeting a AWS Lambda function

The topology diagram shows that Klotho has generated IaC targeting AWS to deploy an API Gateway that invokes a Lambda function serving the application.

Deploying the application

Once the IaC has been generated, you can deploy the cloud-native version of the application with Pulumi.

First, use the Pulumi CLI to set the region aws:region setting for the application's Pulumi stack. This is the AWS region that Pulumi will deploy the application to.

pulumi config set aws:region <region> --cwd './compiled' --stack ts-graphql-yoga

Press ENTER () to confirm that you want to create the ts-graphql-yoga Pulumi stack.

If you would like to create this stack now, please press <ENTER>, otherwise press ^C:
Created stack 'ts-graphql-yoga'

Next, change the current working directory to ./compiled and install the dependencies of the Pulumi application generated by Klotho.

cd compiled
npm install

Then deploy the application by running pulumi up.

pulumi up

Pulumi will display a preview of all the cloud resources it will create as part of the deployment.

Previewing update (ts-graphql-yoga)

Type Name Plan
+ pulumi:pulumi:Stack ts-graphql-yoga-ts-graphql-yoga create..
+ ├─ awsx:ecr:Repository ts-graphql-yoga create
+ │ └─ aws:ecr:LifecyclePolicy ts-graphql-yoga create
+ ├─ aws:ecr:Repository ts-graphql-yoga create
+ ├─ aws:apigateway:RestApi graphql-yoga-gateway create
+ │ ├─ aws:apigateway:Resource graphql-yoga-gatewaygraphql/ create
+ │ │ └─ aws:apigateway:Method ANY-graphql-e6862 create
+ │ │ └─ aws:apigateway:Integration lambda-ANY-graphql-e6862 create
+ │ ├─ aws:apigateway:Resource graphql-yoga-gatewaygraphql/{rest+}/ create
+ │ │ └─ aws:apigateway:Method ANY-rest-d5c2f create
+ pulumi:pulumi:Stack ts-graphql-yoga-ts-graphql-yoga create
+ │ └─ aws:apigateway:Deployment graphql-yoga-gateway-deployment create
+ │ └─ aws:apigateway:Stage graphql-yoga-gateway-stage create
+ ├─ aws:iam:Role ts-graphql-yoga_0d6e4_LambdaExec create
+ │ ├─ aws:iam:Policy ts-graphql-yoga-main-exec create
+ │ └─ aws:iam:RolePolicyAttachment ts-graphql-yoga-main-exec create
+ ├─ aws:cloudwatch:LogGroup main-function-api-lg create
+ ├─ aws:iam:RolePolicyAttachment ts-graphql-yoga-main-lambdabasic create
+ ├─ aws:s3:Bucket create
+ ├─ aws:lambda:Function main create
+ ├─ aws:lambda:Permission ANY-graphql-permission create
+ └─ aws:lambda:Permission ANY-graphqlrest-permission create

apiUrls : [
[0]: output<string>
deploymentPortal: "None - Opted out of topology upload by default"

+ 22 to create

Do you want to perform this update? [Use arrows to move, enter to select, type to filter]
> yes

Select yes from the displayed options to start the deployment process and then wait until Pulumi has completed the deploying the application's stack. This usually takes 3 minutes.

When Pulumi has finished deploying, you will see the completion status and the AWS provided API Gateway URL for your API:

apiUrls : [
[0]: "https://<gateway_id>.execute-api.<region>"
deploymentPortal: "None - Opted out of topology upload by default"

+ 22 created

Duration: 2m31s

Testing the Deployed Application

To test the application one it has been deployed to the cloud, use your browser to navigate to the generated API Gateway's /graphql route.


This will load the GraphiQL, an in-browser GraphQL IDE which we can use to execute the hello query.

screenshot of executing the hello query in GraphiQL and the resulting output: hello from Klotho

Copy the hello query to your GraphiQL window and try it out for yourself!

query {


When you're done with the tutorial, you can destroy the created resources by running pulumi destroy from the ./compiled directory and selecting yes when prompted.

pulumi destroy