AWS AppSync GraphQL API with Golang Lambda source

February 20th, 2018 • 698 Words

GraphQL has been a buzzword for a while now. I immediately fell in love with it when GitHub announced a public GraphQL API. A few weeks ago AWS introduced AppSync, a serverless GraphQL with support for custom data sources using AWS Lambda. Together with the recently introduced Go support for AWS Lambda, this is just awesome!

*Update (New): If you enjoy GraphQL and AppSync or just want to see the latest guide, you should see the updated document and example project about appsync-resolvers, CloudFormation and SAM. The setup can be cleaned up a even more and uses a generic approach for resolver handling.*

*Update (Old): This guide uses the AWS CLI to setup all AppSync related resources. Amazon recently introduced CloudFormation support for AppSync! Make sure to check the updated guide to have an even more simple setup!*


Parsing an RSS feed is never fun; XML is never fun as well. To enable easy access to my RSS feed, I wanted to create a simple GraphQL API using AWS AppSync. Based on the existing example project to deploy an AWS Lambda function using Go, I create a project to wrap up everything with AppSync: appsync-graphql-rss-proxy-go

The serverless AWS configuration with Serverless Application Model is dead simple, but the lack of CloudFormation support for AWS AppSync makes the deployment of the API a bit tricky:


To create the AppSync GraphQL API, you will need the awscli. On a macOS system, just install it with homebrew:

$ > brew install awscli

Install Go packages

For building the Golang Lambda function, two Go dependencies are needed. Use go get to install them.

# make dependencies

$ > go get
$ > go get

Configure Environment

Create a .env file inside the project folder with your basic configuration. As AppSync is not available in all regions, check availability first. You can use us-west-1 as default.



The included main.go file fetches an RSS feed, parses the data, and returns a simple list of the most recent items:

type Post struct {
  URL   string    `json:"url"`
  Title string    `json:"title"`
  Date  time.Time `json:"date"`

func handleRequest(req events.APIGatewayProxyRequest) (interface{}, error) {
  feed, err := rss.Fetch(os.Getenv("URL"))

  if err != nil {
    return nil, errors.New("Cannot fetch RSS feed")

  list := []Post{}

  for _, item := range feed.Items {
    list = append(list, Post{item.Link, item.Title, item.Date})

  return list, nil

Per default, the Lambda function will crawl the RSS feed of this domain, but you can configure the URL of the RSS feed in the environment variables inside the template.yml CloudFormation configuration file.

Thanks to the Serverless Application Model, deploying your AWS Lambda function is dead simple these days:

# Create S3 Bucket
$ > make configure

# Upload data to S3 Bucket
$ > make package

# Deploy CloudFormation Stack for Lambda function
$ > make deploy

# Get Lambda information
$ > make outputs

    "OutputKey": "HandlerArn",
    "OutputValue": "arn:aws:lambda:us-east-1:1234567890:function:your-cloudformation-stack-name-Handler-S5V98FXUK8QT",
    "Description": "ARN for Go Handler"
    "OutputKey": "RoleArn",
    "OutputValue": "arn:aws:iam::1234567890:role/appsync-graphql-rss-proxy-go-Role-18N2ACCHT0MRM",
    "Description": "ARN for IAM Role"

Store the OutputValue for HandlerArn and RoleArn somewhere, you will need them in a few steps.


Currently, neither CloudFormation is supported by AppSync, nor is an integration with AWS Serverless Application Model in place. But luckily, the AWS CLI is here to safe the day! Run make create-api to setup the basics for your AppSync GraphQL API:

$ > make create-api

  "graphqlApi": {
    "name": "appsync-graphql-rss-proxy-go",
    "apiId": "5qemu9oyli88sho8tl5rh0ejpil",
    "authenticationType": "API_KEY",
    "arn": "arn:aws:appsync:us-east-1:1234567890:apis/5qemu9oyli88sho8tl5rh0ejpil",
    "uris": {
      "GRAPHQL": ""

Store the URL for GRAPHQL somewhere safe; you will need it for sending requests to your GraphQL API afterward. For all upcoming commands you will need the apiId value, so copy it to your clipboard or write it down somewhere as well.

Upload GraphQL Schema

The example project on GitHub includes a GraphQL schema; it’s stored in schema.graphql and has basic types to query items in an RSS feed.

type Post {
  url: String
  title: String
  date: String

type Query {
  feed: [Post]

schema {
  query: Query

You need to use the graphqlApi.apiId parameter from the previous command to upload the schema.graphql file to AWS and update your AppSync API:

$ > API_ID=5qemu9oyli88sho8tl5rh0ejpil \
    make create-api-schema

  "status": "PROCESSING"

After having the API in place and the GraphQL schema configured, it’s time to setup the custom data sources for your API!

When you deployed your Lambda function and ran make outputs, you saw a few information about the CloudFormation stack, right? Now it’s time to make use of them! Replace the ARN for the Lambda function and the ARN for the IAM Role in the next command:

$ > API_ID=5qemu9oyli88sho8tl5rh0ejpil \
    LAMBDA=arn:aws:lambda:us-east-1:1234567890:function:your-cloudformation-stack-name-Handler-S5V98FXUK8QT \
    ROLE=arn:aws:iam::1234567890:role/appsync-graphql-rss-proxy-go-Role-18N2ACCHT0MRM \
    make create-api-data-source

  "dataSource": {
    "dataSourceArn": "arn:aws:appsync:us-east-1:1234567890:apis/5qemu9oyli88sho8tl5rh0ejpil/datasources/RSSProxy",
    "name": "RSSProxy",
    "type": "AWS_LAMBDA",
    "serviceRoleArn": "arn:aws:iam::1234567890:role/appsync-graphql-rss-proxy-go-Role-18N2ACCHT0MRM",
    "lambdaConfig": {
      "lambdaFunctionArn": "arn:aws:lambda:us-east-1:1234567890:function:appsync-graphql-rss-proxy-go-Handler-S5V98FXUK8QT"

With the custom data source in place, you can now connect it to your GraphQL schema as a custom resolver:

$ > API_ID=jrwgynjw6jfmdevmqlrknewqna \
    make create-api-resolver

  "resolver": {
    "typeName": "Query",
    "fieldName": "feed",
    "dataSourceName": "RSSProxy",
    "resolverArn": "arn:aws:appsync:us-east-1:1234567890:apis/5qemu9oyli88sho8tl5rh0ejpil/types/Query/resolvers/feed",
    "requestMappingTemplate": "{ \"version\" : \"2017-02-28\", \"operation\": \"Invoke\", \"payload\": $util.toJson($context.arguments) }",
    "responseMappingTemplate": "$util.toJson($context.result)"

Using the GraphQL API

To test your GraphQL API you will need an API key. Luckily this can be created using the CLI as well.

$ > API_ID=jrwgynjw6jfmdevmqlrknewqna \
    make create-api-key

  "apiKey": {
    "id": "da2-nuyzhanm5bcptga6yilkj7zluy",
    "expires": 1519725600

You can use curl to test your API or use a GraphQL UI. Just make sure to configure the needed authentication header with your API Key:

$ > curl \
    -XPOST \
    -H "Content-Type:application/graphql" \
    -H "x-api-key:da2-nuyzhanm5bcptga6yilkj7zluy" \
    -d '{ "query": "query { feed { title url } }" }' | jq

  "data": {
    "feed": [
        "title": "Deploy Golang Lambda with AWS Serverless Application Model",
        "url": ""
        "title": "68% Mechanical Keyboard with",
        "url": ""


That’s awesome, right? What’s your setup to deploy and maintain a GraphQL API using AWS AppSync? Let me know on Twitter what you this about this approach and if you know of any way to already do this with CloudFormation!

View on GitHubSource code is published using the MIT License.
  • React SPA with server-side rendering on AWS Lambda

    February 5th, 2020 • 1152 Words • EN

    React is great for creating websites and writing applications using JavaScript. But, whenever the use of React is rejected, one of the most common reasons is the lack of a simple implementation for server-side rendering (SSR). When you search on Google for this topic, you’ll find various approaches…

  • Deploy React SPA with CodePipeline and CodeBuild using AWS CDK

    January 23rd, 2020 • 748 Words • EN

    There are plenty of tools and services for continuous delivery available. Most of them are either directly built into the source code management tools you already use, or perfectly integrate with them. You might be familiar with CircleCI, Travis CI, GitLab CI, or GitHub Actions. Of course, AWS has…

  • AWS re:Invent 2019 Recap & Videos

    December 15th, 2019 • 360 Words • EN

    I was able to attend the AWS re:Invent 2019 conference. A week full of learning about current and new technologies, services, and general approaches is definitely overwhelming. There is no much content available, during the conference, and as videos and slide decks afterwards. I tried to list my…

  • CloudFormation Best-Practices

    May 1st, 2019 • 457 Words • EN

    You can find plenty of frameworks and tools to provision your AWS resources. Some of them do a great job for a specific purpose, others are more generic. Nevertheless, I do prefer to use native CloudFormation templates as much as possible. Prefix all the things Split up your CFN Stacks Nested…

  • Makefile Best-Practices

    April 30th, 2019 • 167 Words • EN

    The more projects you work on, the more streamlined your tooling gets. Hopefully. Various services using different languages have different tooling requirements, of course. A sweet Makefile can be the entry to a unified tooling interface. Hide Commands Wildcard Targets Foreach and Lists As long as I…

  • Last Update: 2020-02-17T10:07:11.183Z
    Stresemannstraße 132, 22769 Hamburg
    +49 151 54 64 90 55