While using AWS AppSync you'd usually reach AWS CloudFormation limits related to number of resources (200) and number of parameters (60) per stack when the number of operations in the schema grows.
Applicable when
- Using AppSync in the project and you expect to have more than 50 operations in your API.
Non-applicable when
- AppSync's API will have less than 50 operations
Implementation
NOTE: Make sure of being using AWS CDK >= 1.61.0. In 1.45.0 great improvement on how stack parameters are handled was introduced. It would create a map of them into S3 bucket and point to them as required so actual stacks can handle many more parameters in a single one. Unfortunately, until 1.61.1 there is no bug free implementation on that. At the moment of writing this document, latest version is 1.63.0 and works fine.
NOTE: Due to AWS CDK version, regions must be bootstrapped using version 4. If your region is not using that version it will fail asking you to upgrade it. Just running in example
cdk bootstrap aws://123456789/us-east-1
should upgrade it without issues. Please note that account number and region must match the ones you're using. If for some reason it does not works, you can always go to AWS CloudFormation console and remove the CDK Toolkit stack manually, and just bootstrap the region from scratch.
The main idea resides on the usage of NestedStack construct to generated as many child stacks as required in order to provision your resolvers (CfnResolver).
Assuming that we have a list of resolvers (resolversList) and a stack to provision AppSync API (ApiGraphqlStack), what we need to do is:
- Split resolversList
- Create a new stack for each chunk of resolversList
In the example, ApiGraphqlResolversStack is the parent stack, we split the resolvers by type, and those by stack limit. Split coeficient is set to 50 to make sure that 60 parameters length per stack is not reached. Usually, if your API configuration does not uses Pipelines resolvers, you should be fine with some value like 150 instead. Then, each chunk is safe to be provisioned into a new ApiGraphqlResolversResourcesStack stack:
export class ApiGraphqlResolversStack extends NestedStack {
private readonly stackLimit = 50;
...
constructor(
scope: Construct,
id: string,
resolversList: ResolverConfiguration[],
api: ApiGraphqlStack,
...
) {
...
const queries: ResolverConfiguration[] = [];
const mutations: ResolverConfiguration[] = [];
resolversList.forEach(resolver => {
if (resolver.type === 'Query') {
queries.push(resolver);
} else if (resolver.type === 'Mutation') {
mutations.push(resolver);
}
});
this.createResources('queries', queries, api);
this.createResources('mutations', mutations, api);
}
private createResources(
id: string,
resolvers: ResolverConfiguration[],
api: ApiGraphqlStack,
): void {
const splitted = this.splitResolvers(resolvers);
splitted.forEach((items, index) => {
new ApiGraphqlResolversResourcesStack(
this,
`${id}resolvers${index}`,
api,
items,
);
});
}
private splitResolvers(resolvers: ResolverConfiguration[]): ResolverConfiguration[][] {
const resolversArray: ResolverConfiguration[][] = [];
for (let index = 0; index < resolvers.length; index++) {
if (index % this.stackLimit === 0) {
resolversArray.push([]);
}
resolversArray[Math.floor(index / this.stackLimit)].push(resolvers[index]);
}
return resolversArray;
}
}
Detail of ApiGraphqlResolversResourcesStack:
export class ApiGraphqlResolversResourcesStack extends NestedStack {
constructor (
scope: Construct,
id: string,
api: ApiGraphqlStack,
resolvers: ResolverConfiguration[],
props?: NestedStackProps
) {
super(scope, id, props);
resolvers.forEach(resolver => {
const options: CfnResolverProps = {
apiId: api.api.attrApiId,
fieldName: resolver.field,
typeName: resolver.type,
kind: 'UNIT',
requestMappingTemplate: resolver.requestMappingTemplate,
responseMappingTemplate: resolver.responseMappingTemplate,
};
new CfnResolver(this, `${resolver.name}_resolver`, options);
});
}
}
With this recipe you'll be able to alter the schema, provision and deploy consistently without the needing of destroying the stack.
Find a working example at 5k Sococo api-graphql-*.stack.ts files.
Comments
0 comments
Please sign in to leave a comment.