In the evolving world of serverless architecture, the developer experience is a commonly debated topic. In particular, the challenges associated with testing locally and obtaining a fast feedback loop.
Nowadays, we have a few technologies that make it convenient to develop serverless applications locally, enabling a swift integration between your local environment and the cloud (e.g. SAM Sync, CDK Watch and SST Live Lambda).
In a previous article, I demonstrated how to use the SST Live Lambda with a small project that uses a deployed endpoint in AWS API Gateway to invoke a locally developed Lambda.
I wanted to know how this works. Through this post, I aim to delve into the specifics of the underlying architecture of the SST Live Lambda functionality. For the official docs, you can find them here.
Requests are proxied to the local machine
SST docs state that the requests are proxied to the local machine, which allows SST to run the local version of the function with the event, context and credentials of the remote Lambda function. The communication between local and remote happens using AWS IoT over WebSocket.
Let's check the details!
- Create a new SST project: ```
npx create-sst@latest
? Project name demo-sst
✔ Copied template files
Next steps:
- cd demo-sst
- npm install (or pnpm install, or yarn)
- npm run dev
* Run `npm install` to install the dependencies
* Update the `stacks` directory with the resources you'd like to provision
* Run `npm run dev` to start the project
Two things happen When you run `npm run dev`:
### SST creates a bootstrap stack in CloudFormation
The stack creates resources that are needed in the deployment process of your app (more details [here](https://docs.sst.dev/advanced/bootstrapping)).
Note that each app needs to be bootstrapped once, so the next time we run `npm run dev` this step won't be executed.
As this article is focused on the Live Lambda, we will only focus on the bootstrap script a little. In summary, the following resources were created:
- An S3 bucket that stores critical information about the apps (e.g. prod/dev mode, the config needed to store secrets and variables, etc.).
- A Lambda function that automatically deletes the S3 bucket objects when they are no longer needed
- A lambda function that handles the collection and uploading of metadata to the S3 bucket
- An EventBridge rule that triggers the MetadataHandler Lambda function
### SST Deploys Your Application Resources
SST deploys the application resources as defined in the `stacks` directory, enabling the usage of the Live Lambda feature.
Let's look at some details beyond what's mentioned in the SST documentation.
I deployed a simple stack that includes API Gateway and a Lambda function:
import { StackContext, Api } from 'sst/constructs';
export function API({ stack }: StackContext) {
const api = new Api(stack, 'api', {
routes: {
'GET /': 'packages/functions/src/lambda.handler',
},
});
stack.addOutputs({
ApiEndpoint: api.url,
});
}
You can see the resources in CloudFormation and verify that the API Gateway and the Lambda function were created successfully.
First, the deployment will include all the resources defined in the `stacks` directory but will stub the lambda function by one defined by SST (not the real lambda function having your code). The diagram would look as follows:
![SST Live Lambda Deployment](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dsbdi5yk381ioqqesfow.png)
- The "Deployed Stack" is what you defined but with a stub lambda function
- The AWS account is configured with a default IoT endpoint in each region. SST will use that endpoint based on the region configured `sst.config.ts`
- SST starts a local WebSocket client and connects to that IoT endpoint.
Once the stack is deployed, we're outputting the API Gateway Endpoint that we can request. Send a GET request to this endpoint (e.g. `curl https://ser55ggwrf.execute-api.us-east-1.amazonaws.com`). Below is how the flow works:
![SST Live Lambda Invocation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i9xrv2b9ure21toqwf1w.png)
There are still more details to be discovered, especially on how the comms happen between the IoT endpoint and the stub Lambda, and the response relayed back to that Lambda.
Top comments (1)
Very interesting post. I was missing the part of how the local lambda is executed and payload is passed to stub lambda.
When you run sst dev, it deploys your app and replaces the Lambda functions with a stub version.
It also starts up a local WebSocket client and connects to your AWS accounts' IoT endpoint.
Now, when a Lambda function in your app is invoked, it publishes an event, where the payload is the Lambda function request.
Your local WebSocket client receives this event. It publishes an event acknowledging that it received the request.
Next, it runs the local version of the function and publishes an event with the function response as the payload. The local version is run as a Node.js Worker.
Finally, the stub Lambda function receives the event and responds with the payload.