How to connect appsync and lambda

How to connect appsync and lambda

·

4 min read

Intro

The article is not intended for beginners and will not explain what GraphQL is or how to install Node.js or setup aws cli. Instead, it will focus on personal experience and info that hard to find. it's advisable to have some free time, and a healthy sense of curiosity.

What is appsync ?

This is a GraphQL server from AWS Amazon.

In AppSync, resolvers can be written in either JavaScript or can call an external lambda function and this lambda can handle all the logic. I prefer using Lambda because the runtime functionality for resolvers within AppSync is extremely limited. Example of limitations of js resolvers you can see by url docs.aws.amazon.com/appsync/latest/devguide..

Here are some examples:

  1. apply, bind, and call methods not are supported.

  2. Function constructors are not supported.

  3. Passing a function as an argument is not supported.

  4. Recursive function calls are not supported.

  5. Async processes are not supported, and promises are not supported.

IMHO Looks terrible. Impossible to write complex code.

AppSync drawbacks

TLDR: You'll be solving problems that would never have arisen if you had chosen a different approach. For example

With lambda as resolver, you have request flow like

  1. A request comes from the user.

  2. AppSync parses the request.

  3. It transforms it into an object and sends it to the Lambda function over the network.

  4. The Lambda function parses it, interacts with the database, computes the response, and sends it back to AppSync.

  5. AppSync delivers the response to the user.

On the other hand with apollo:

  1. A user request arrives.

  2. Apollo parses it.

  3. It handle with same memory process , unlike AppSync, which does it over the network.

  4. The resolver interacts with the database, performs calculations, etc.

  5. And then returns this to the user.

Compared to a GraphQL server,

  1. AppSync introduces an extra network request.

  2. Additionally, in the Lambda scenario, you would have to address the N+1 query problem at the Lambda level, without utilizing the Data Loader pattern.

Some other drawbacks

  1. Also, AppSync does not support documentation in the GraphQL schema using triple quotes ("""), only hardcore "#" comments.

  2. It has not supported documentation within enums for four years now! Link to the issue.

How to connect lambda and appsync ?

I prefer using the Serverless Framework and its associated plugin serverless-appsync-plugin.

Attention, the instructions for the serverless-appsync-plugin on the website serverless.com/plugins/serverless-appsync-p.. are outdated. Don't use it. Looks at real doc on github.com/sid88in/serverless-appsync-plugi...

Quckstart

clone my template repo

git clone https://github.com/R11baka/appsynctemplate && cd appsynctemplate

After that run

npm install

Useful commands that appear after installing the serverless-appsync-plugin.

npx sls appsync validate-schema

Schema validation. It partially ensures that your schema is valid. It won't save you if you have comments within an enum.

What's going on ?

The heart of application and most tricky, from my point of view is serverless.yaml file. Let's try to see

service: appsync-demo  
frameworkVersion: "3"
configValidationMode: "warn"

provider:
  name: aws
  runtime: nodejs18.x
  stage: ${opt:stage, self:custom.defaultStage}
  region: us-west-1
  versionFunctions: true
  logRetentionInDays: 90
  environment:
    AWS_NODEJS_CONNECTION_REUSE_ENABLED: 1

plugins:
  - serverless-appsync-plugin # attach appsync-plugin to serverless
custom:
  defaultStage: dev

appSync:
  name: appsync-demo-${self:provider.stage}
  schema: 'schema.graphql' # path relative to serverless.yaml file
  authentication:
    type: 'API_KEY' # type of auth. Also can be cognito, and custom AWS_LAMBDA
  apiKeys:
    - name: apiKey
      description: dev API key
      expiresAfter: 1M
  dataSources:
    appsyncLambdaDataSource:
      type: AWS_LAMBDA
      name: appsyncLambda
      config:
        functionName: appsyncLambda # name of lambda
  resolvers:
    query:
      type: Query # Hello resolver
      field: hello
      dataSource: appsyncLambdaDataSource 
      kind: UNIT

functions:
  appsyncLambda:
    name: appsyncLambda-${self:provider.stage}
    description: Lambda resolver which accept events from appsync
    timeout: 15
    handler: src/index.handler # points to main entry point

So tricky part is definition datasource, resolver, lambdaname.

  1. Resolver on 36 line points to datasource with name appsyncLambdaDataSource.

  2. appsyncLambdaDataSource point on lambda with name appsyncLambda, which defined on 43 line

How to deploy ?

Deploy to dev

npx sls deploy --stage=dev --verbose

Deploy to live

npx sls deploy --stage=live --verbose

After deploy you will see in console output something like

Stack Outputs:
  AppsyncLambdaLambdaFunctionQualifiedArn: arn:aws:lambda:us-west-1:7412810041:function:appsyncLambda-dev:5
  ServerlessDeploymentBucketName: appsync-demo-dev-serverlessdeploymentbucket-u48ln3fiu
appsync endpoints:
  graphql: https://s6ghsxmtbnfaxperetsottu.appsync-api.us-west-1.amazonaws.com/graphql
  realtime: wss://s6ghsxmtbnfaxpp2u4metsottu.appsync-realtime-api.us-west-1.amazonaws.com/graphql
appsync api keys:
  da2-gihxmtd34bf2ncouh2nseu (dev API key)

Go to the studio.apollographql.com/sandbox/explorer?r.., paste graphqlurl in top. And add header x-api-key: da2-gihxmtd34bf2ncouh2nseu to the headers sections. You ready to request appsync