Enhancing AppSync API Creation with Serverless Stack

Serverless Stack (SST) is a powerful framework that allows developers to build serverless applications quickly and efficiently. One of the many capabilities it offers is the ability to create AppSync APIs. However, as developers, we sometimes encounter certain limitations in the prescribed approaches that could potentially affect our application’s performance. In this blog post, I’m going to discuss an alternative approach to creating AppSync APIs with SST using TypeScript. This new approach addresses the limitation in the SST documentation, where the absence of event and context in the lambdas can lead to problems, especially when needing to read sub,Cognito groups or Cognito PoolID from a given request.

Current Approach

According to SST documentation, the way to create an AppSync API in TypeScript looks something like this:

type AppSyncEvent = {
info: {
fieldName: string;
};
arguments: {
note: Note;
noteId: string;
};
};

export async function handler(
event: AppSyncEvent
): Promise<Record<string, unknown>[] | Note | string | null | undefined> {
switch (event.info.fieldName) {
case "listNotes":
return await listNotes();
//other cases
default:
return null;
}
}

In this approach, we define a type, AppSyncEvent, which holds information about the event. We then create an asynchronous handler function that takes an AppSyncEvent as a parameter. The function then switches on event.info.fieldName to determine how to handle the request.

Problem with the Current Approach

While this approach works for many scenarios, it falls short in others. When working with AWS, the lambdas’ event and context are often required to extract information like Cognito groups or sub. The limitation here is that the current SST approach does not allow for these parameters in the lambda function, causing a lack of necessary information for certain processes.

Proposed Solution

To overcome these challenges, I propose an alternative approach where we include event and context in our lambda function, like so:

import { Context } from "aws-lambda";

export async function handler(
event: any,
context : Context
): Promise<Record<string, unknown>[] | Note | string | null | undefined> {
// Add your logic here
}

By defining event as any and including context of type AWSLambda.Context, we can now access all the information that the event and context hold. This can be crucial when needing to read sub or Cognito groups and can lead to better application performance.

Demonstrating the New Approach

Let’s say we want to access the Cognito groups in our lambda function. With the new approach, we could do it like this:


//Main handler

import { CognitoIdentityProvider } from 'aws-sdk';

export async function handler(
event: any,
context: AWSLambda.Context
): Promise<Record<string, unknown>[] | Note | string | null | undefined> {

console.log(event.identity.claims.sub) //User Sub
console.log(event.identity.claims["cognito:groups"]) //Any cognito groups
console.log(event.identity.claims["iss"].split("/")[3]) //Cognito pool id
switch (event.info.fieldName) {
case "listNotes":
return await listNotes();

default:
return null;
}
}

Also because we have the context we can manage connections like MongoDB connections in our lambda

export async function handler(
event: any,
context: Context
): Promise<FitbitSynced> {

context.callbackWaitsForEmptyEventLoop = false;

//Rest of your logic
}

Setting context.callbackWaitsForEmptyEventLoop to false can be useful when you have asynchronous operations running in the background, such as database connections or HTTP requests, and you don't want to wait for them to complete before terminating the Lambda function. This can help to reduce the execution time of the function.

Conclusion

In conclusion, while the standard SST approach for creating an AppSync API works in most cases, it can limit the access to crucial information in certain scenarios. By adjusting the handler function to include event and context, we can overcome this limitation and create more efficient serverless applications.

Let me know your thoughts on this approach, and if you’ve found other ways to improve AppSync API creation with SST. Happy coding!

--

--