Building dependable and scalable applications in the ever-changing world of software development today calls for state-of-the-art resources and services. One notable innovation that changes the game is AWS AppSync, which makes creating GraphQL APIs with real-time data updates easier. As more developers take advantage of GraphQL’s advantages, AWS AppSync’s Merge API proves to be a potent tool for effectively managing intricate data relationships.
This article explores how to use AWS SAM to incorporate the AWS AppSync Merge API into your application effortlessly. By the conclusion, you’ll be able to easily integrate AppSync Merge API into your projects and have a thorough understanding of its nuances.

Understanding AWS AppSync Merge API

Let’s take time to understand the relevance of AWS AppSync Merge API before moving on to the integration procedure. By enabling developers to request just the data they require, GraphQL, in contrast to conventional RESTful APIs, minimizes the problems of over- and under-fetching. With the Merge API, AppSync, AWS’s fully managed GraphQL service, expands these possibilities even further.
Several data sources can be combined into a single GraphQL API with the help of the AppSync Merge API, offering a consistent interface for data updating and querying. This makes managing intricate interactions between different data kinds easier, which promotes a more effective and natural development process. You may combine data from several sources, such as AWS DynamoDB, Lambda functions, and more, into a coherent GraphQL schema by using the Merge API.

You will be guided step-by-step through the process of defining the AWS SAM templates required to configure the AppSync Merge API by following this guide.

Architecture

This application comprehends two simple microservices for users and tickets. They can be managed and deployed independently; their schemas will be merged by the AppSync merge API which is also the gateway of the entire architecture. To understand how to build a single microservice using AppSync check this out: https://medium.com/aws-serverless-world/deploy-appsync-graphql-api-with-sam-part-one-18287b55951b.

Codebase

The code for this project is here: https://github.com/stech-world/appsync-mergeAPI. The repo is divided in three folders:

Both of the three folders contain a simple AWS SAM project with a separate template file.
Two of them contain a simple AppSync project like the one described here with a bit more that will be explained lately.
The folder merge-api contains the resources for the MergeAPI to deploy.
You can consider the three folders separately like they are three different repos also managed by three different teams; simplicity is the only reason why they are inside the same project.

Merge API

Let’s start with the merge API template:


AppSyncApiKey:
Type: AWS::AppSync::ApiKey
Properties:
ApiId: !GetAtt AppSyncMergeAPI.ApiId

AppSyncMergeAPI:
Type: AWS::AppSync::GraphQLApi
Properties:
Name: !Sub ${APIName}
ApiType: MERGED
AuthenticationType: API_KEY
MergedApiExecutionRoleArn: !GetAtt AppSyncMergeAPIExecutionRole.Arn

This AWS SAM template includes two resource definitions. The first one is an AppSync API key named “AppSyncApiKey” of type AWS::AppSync::ApiKey. It has a property “ApiId” set to the value obtained using the intrinsic function !GetAtt, specifically referencing the “ApiId” attribute of the “AppSyncMergeAPI” resource.

The second resource is an AppSync GraphQL API named “AppSyncMergeAPI” of type AWS::AppSync::GraphQLApi. It has several properties set using the !Sub and !GetAtt intrinsic functions. The “Name” property is set by substituting the value of the “${APIName}” variable. The “ApiType” property is set to “MERGED” (this is different from the other default type which is “GRAPHQL”), and the “AuthenticationType” property is set to “API_KEY.” The “MergedApiExecutionRoleArn” property is set using the !GetAtt intrinsic function to reference the “Arn” attribute of the “AppSyncMergeAPIExecutionRole” resource.

The policy of the following role is important because allows the merge API to initiate the merge operation that will be settled as AUTO in the users and ticket services template:

  AppSyncMergeAPIExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: appsync.amazonaws.com
Action: sts:AssumeRole
Condition:
StringEquals:
aws:SourceAccount: !Sub ${AWS::AccountId}
ArnLike:
aws:SourceArn: !Sub arn:aws:appsync:${AWS::Region}:${AWS::AccountId}:apis/*
Path: /
Policies:
- PolicyName: AppSyncMergeAPIPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- appsync:StartSchemaMerge
Resource:
- !Sub arn:aws:appsync:${AWS::Region}:${AWS::AccountId}:apis/*

I suggest you add to outputs that will be useful during the microservices deployment:

Outputs:
MergeAPIId:
Value: !GetAtt AppSyncMergeAPI.ApiId
MergeAPIRoleArn:
Value: !Ref AppSyncMergeAPIExecutionRole

This information will be used as parameters of the ticket and user services and injected via samconfig.toml.

parameter_overrides = """
APIName="Ticket API" \
MergedApiIdentifier="<merge API indentifier>" \
MergeApiExecutionRoleName="<merge API execution role ARN>"
"""

It’s time to deploy the MergeAPI!
Running an AWS SAM (Serverless Application Model) application involves several steps. SAM provides a set of command-line interfaces (CLI) to help you deploy, manage, and test your serverless applications. Below are the general steps to run an AWS SAM application:

Prerequisites:

  1. Install AWS CLI: Make sure you have the AWS CLI installed on your machine. If you want more details, check this out: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html
  2. Install SAM CLI:
  3. Install the AWS SAM CLI on your machine. You can download it from here.

Steps to Run an AWS SAM Application:

  1. Navigate to the SAM Project: open a terminal and navigate to the root directory of your SAM project.
  2. Build the SAM Application: sam build . This command compiles your application code, fetches dependencies, and creates a deployment package in the .aws-sam directory.
  3. Deploy the SAM Application: sam deploy --profile <YOUR PROFILE NAME>. This command will use the configuration already provided inside the samconfig.toml file.
  4. Cleanup (Optional): sam delete. This will remove the application from the AWS cloud

Your deployment should succeed and you can check in the AWS console the merge API created

Ticket and User Services

Let’s discuss now what to do for the single services: ticket and user in this example.
All the steps are already described here except for a few things that will be described below.

I’ll begin to list the new parameters inside the template file:

Parameters:
...
MergedApiIdentifier:
Type: String
Description: The name for the AppSync GraphQL Merge API for the merge association.
Default: ""
MergeApiExecutionRoleName:
Type: String
Description: The ARN of the AppSync Merge API Execution Role.
Default: ""

These parameters are the info that our service will use to merge with the merge API already deployed. It is possible to find the ID and role name in the output of the merge API template:

… or in the CoudFormation console

As you can see I set a default value for these parameters. This is why, if they are not provided, this GraphQL API works perfectly standalone to make all the services independent of each other.

I also defined a condition to detect if the merge API has been defined. This condition will handle the SourceApiAssociation resource we will describe below

Conditions:
IsMergeApiDefined: !Not [!Equals [!Ref MergedApiIdentifier, ""]]

The SourceApiAssociation resource “Describes the configuration of a source API. A source API is a GraphQL API that is linked to a merged API. There can be multiple source APIs attached to each merged API. When linked to a merged API, the source API’s schema, data sources, and resolvers will be combined with other linked source API data to form a new, singular API. Source APIs can originate from your account or from other accounts via Resource Access Manager.”

Resources:
SourceApiAssociation:
Condition:
IsMergeApiDefined
DependsOn:
- AppSyncUserSchema
Type: AWS::AppSync::SourceApiAssociation
Properties:
MergedApiIdentifier: !Ref MergedApiIdentifier
SourceApiAssociationConfig:
MergeType: AUTO_MERGE
SourceApiIdentifier: !GetAtt AppSyncUserAPI.ApiId

This resource is conditional: only if the MergeApiIdentifier parameter has been set. The MergeApiIdentifier property indicates which Merge API to merge with and the SourceApiAssociationConfig property indicates that the merge operation will happen automatically during the deployment, no manual operations are needed.

Another conditional resource is the policy to associate with the Merge API execution role to allow the Merge API to interact with the service we are deploying:

  MergeApiExecutionRolePolicyAssociation:
Condition:
IsMergeApiDefined
Type: AWS::IAM::Policy
Properties:
PolicyName: !Sub MergeApiExecutionRolePolicyAssociationFor-${AppSyncUserAPI.ApiId}
Roles:
- !Ref MergeApiExecutionRoleName
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- appsync:SourceGraphQL
Resource:
- !Sub arn:aws:appsync:${AWS::Region}:${AWS::AccountId}:apis/${AppSyncUserAPI.ApiId}
- !Sub arn:aws:appsync:${AWS::Region}:${AWS::AccountId}:apis/${AppSyncUserAPI.ApiId}/*

Finally, I suggest you add an Output to identify whether the merge operation is successful or not:

Outputs:
SourceApiAssociationStatus:
Condition:
IsMergeApiDefined
Value: !GetAtt SourceApiAssociation.SourceApiAssociationStatus

… deploy the services (the order doesn’t matter) and you should have your everything up and running!!

In this post, I won’t explain the details regarding the merge in schemas and resolver. This is only dedicated to the AWS SAM and deployment arguments. If you are interested in the GraphQL merge schemas you can take a look at the user service schema where is defined an injection to be applied to the ticket service and the relative resolver.

type Ticket {
user: User
}
import { util } from '@aws-appsync/utils';

export function request(ctx) {
const { user } = ctx.source;
return dynamoDBGetItemRequest({ id: user });
}

export function response(ctx) {
ctx.stash.parent = ctx.result;
return ctx.result;
}

function dynamoDBGetItemRequest(key) {
return {
operation: 'GetItem',
key: util.dynamodb.toMapValues(key),
};
}
  GetTicketUserResolver:
Type: AWS::AppSync::Resolver
Properties:
ApiId: !GetAtt AppSyncUserAPI.ApiId
CodeS3Location: ./src/resolvers/getSingleUserFromCTXSource.js
FieldName: user
TypeName: Ticket
DataSourceName: !GetAtt UserTableDataSource.Name
Runtime:
Name: APPSYNC_JS
RuntimeVersion: 1.0.0

If you are looking for more information you can follow this AWS post: https://docs.aws.amazon.com/appsync/latest/devguide/merged-api.html
or keep following me.

See you soon, since then, have a good day.
Bye! 🤗

--

--