DEV Community

Cover image for AppSync Merged API – Our real project experience as part of our hackathon
Julian Michel for AWS Community Builders

Posted on • Originally published at julianmichel.dev on

AppSync Merged API – Our real project experience as part of our hackathon

AWS released a new feature for GraphQL APIs in May: Multiple AppSync APIs can be merged into one overall API. Our AI Hackathon gave us the opportunity to test the new Merged API feature in a real-world project.

Why are Merged APIs such a useful feature?

When designing complex software, it is common to break the application into components or microservices. Each component has its own API so that it can be developed and deployed independently. However, when APIs are published or used in front ends, it makes sense to provide an aggregated API with services of all components. This is possible with the new Merged API feature.

How to create a Merged API using AWS CDK?

We first looked at the AppSync documentation in the AWS CDK to see how to create Merged APIs. Unfortunately, the documentation doesn’t include a section on Merged APIs. We checked the feature requests and pull requests on the AWS CDK GitHub project. However, since we did not find any information, we determined that Merged APIs are not currently supported by CDK L2 constructs. To get support for this feature in AWS CDK, we’ve created a feature request in the AWS CDK project.

So how did we create the Merged APIs?

CloudFormation already includes support for Merged APIs. The documentation describes the attributes and resources which are required. Using CDK L1 constructs, we could use these CloudFormation resources to create the Merged API.

First, we created the necessary IAM roles. Currently they don’t follow the principle of least privilege. When Merged APIs are supported in the CDK, this should also be considered.

const role = new Role(this, `merged-api-role-${props.namespace}`, {
  assumedBy: new ServicePrincipal('appsync.amazonaws.com'),
  roleName: `merged-api-role-${props.namespace}`,
});
role.addToPolicy(new PolicyStatement({
  resources: ['*'],
  actions: ['appsync:*'],
}));

const cwRole = new Role(this, 'MergedAPICWRole', {
  assumedBy: new ServicePrincipal('appsync.amazonaws.com'),
});

cwRole.addToPolicy(new PolicyStatement({
  actions: ['logs:CreateLogGroup',
    'logs:CreateLogStream',
    'logs:PutLogEvents'],
  resources: [`arn:aws:logs:${cdk.Stack.of(this).region}:${cdk.Stack.of(this).account}:*`],
}));
Enter fullscreen mode Exit fullscreen mode

In the GraphQL API, the attributes apiType and mergedApiExecutionRoleArn are specific to Merged APIs. In addition, logging had to be explicitly configured, which requires more effort than L2 constructs.

const api = new CfnGraphQLApi(this, `merged-api-${props.namespace}`, {
  authenticationType: 'API_KEY',
  additionalAuthenticationProviders: [
    {
      authenticationType: 'AMAZON_COGNITO_USER_POOLS',
      userPoolConfig: {
        userPoolId: props.userPool.userPoolId,
        awsRegion: cdk.Stack.of(this).region,
      },
    },
  ],
  apiType: 'MERGED',
  name: cdk.Names.uniqueId(this),
  mergedApiExecutionRoleArn: role.roleArn,
  xrayEnabled: true,
  logConfig: {
    cloudWatchLogsRoleArn: cwRole.roleArn, fieldLogLevel: 'ALL',
  },
});
Enter fullscreen mode Exit fullscreen mode

Each source API is assigned to the Merged API using a SourceApiAssociation.

new CfnSourceApiAssociation(this, name, {
  sourceApiIdentifier: graphqlApi.apiId,
  mergedApiIdentifier: mergedApi.attrApiId,
  sourceApiAssociationConfig: {
    mergeType: 'AUTO_MERGE',
  },
});
Enter fullscreen mode Exit fullscreen mode

The first deployment failed. After specifying mergeType: 'AUTO_MERGE', we were able to create the Merged API.

How did we structure our project?

Each component is developed as separate CDK stack. An additional stack called MergedApiStack includes the Merged API. The source APIs are passed to the Merged API Stack using CDK Stack Props.

This allows us to publish a central AppSync API that includes API methods of all components.

Image description

Summary

Because of the missing CDK L2 constructs, it was difficult to create the Merged API. Otherwise, our experience with the Merged API has been very good. The Merged API is updated directly and allows us to have one central API for our application.

What’s next? We will likely implement an L2 construct to add support for Merged APIs in the AWS CDK. Then our hackathon and community work will also contribute to AWS CDK.

Who to reach out to?
Danielle, Matt, Johannes or myself.

Top comments (2)

Collapse
 
frixaco profile image
Rustam Ashurmatov

Thank you for the article! I'd love to see more articles on this topic.

I'm also trying to create similar backend, but with CloudFormation. Have you run into any errors with error messages similar to this by any chance?: "Resource of type 'AWS::AppSync::SourceApiAssociation' with identifier 'null' did not stabilize."?

Collapse
 
jumic profile image
Julian Michel • Edited

I‘m not sure if I had the same error message. Did you specify MergeType in property SourceApiAssociationConfig? Without MergeType I wasn’t able to deploy the Merged API.