Debugging Node.js Lambda invoked by ApiGateway

Matan Cohen Abravanel
Melio’s R&D blog
Published in
4 min readAug 23, 2021

Debugging tools are fundamental for our day-to-day work as developers. Running a Lambda inside its original environment, with the ability to add breakpoints on the fly, and to watch variable values change in real-time, could save hours and possibly days of debugging.

My personal opinion is that setting up a good development environment pays off in the long term.

There are some good tutorials out there explaining how to trigger specific Lambda functions via sam local invoke function. These are great for some cases, yet spinning up a server which can be triggered via postman is a different level of ease in my opinion.

After a few unsuccessful Google searches, I’ve finally figured out how to debug a Node.js SAM Lambda, invoked by ApiGateway via Webstorm leveraging real-time breakpoints. Here is a short tutorial of how it can be achieved:

Lambda invoked via API-gateway

Starting point

You should already have an AWS Lambda application that is wired to ApiGateway via SAM (Cloud formation)

template.yml

Overview: the first resource is a gateway. In this case, it is generated via open-api specification. I’m not going to go over how it is done, and using open-api is optional. The second resource is the Lambda function. CodeUri specifies where the actual javascript code is located, since the Lambda is written in typescript. It means when debugging, breakpoints should be placed in the build folder js code, since that is the code that is executed.

Lambda handler:

create.ts

When using typescript, before debugging, build your project to generate a js file inside your build folder:

build/create.js generated via npm build

There is already a breakpoint placed on line 6, ready to be triggered, make sure you add one as well.

Before we continue, make sure sam cli and docker are installed on your machine

Now we are going to do the following:

  1. Spin up a sam server on port 3000 which will listen to incoming requests and route them to a docker container.
  2. Spin up a docker container on port 5858 which will receive Lambda triggers. Then attach Webstorm to this container to control execution.

All of this is done via a single command:

$ sam local start-api -d 5858

Output:

Terminal output

Now if you run $ docker ps you will notice there is no container on port 5858 as I previously said there would be. This is because we didn’t trigger a request yet. We can do it via postman:

After executing the request via postman the request should be stuck on “sending request”. Go and check out your terminal:

terminal output after executing request via postman

The server running on port 3000 detected a request and mounted the Lambda function with a docker container on port 5858.

$ docker ps
docker ps output, a running container on port 5858

Awesome, now the only thing we are missing is attaching WebStorm to the container running on port 5858:

Open run debug configuration within WebStorm and select “Attach to node.js/Chrome”
Specify localhost as host on port 5858
hit the “debug” button

Immediately after hitting the “debug” button, your breakpoint will be triggered:

create.js breakpoint triggered

Cool ha? 🕺🏻

If you open your terminal, you will notice that the container was attached to the Webstrom process:

I hope this tutorial helps a few serverless developers with debugging.

Please let me know if it helped, or you found it useful, by hitting the “Clap!” button. 👏

Cheers!

Edit:

Some have requested configuration for the case of VSCode:

{
"type": "node",
"request": "attach",
"name": "Attach to SAM CLI",
"address": "localhost",
"port": 5858,
"localRoot": "${workspaceRoot}/build",
"outFiles": ["${workspaceFolder}/build/**/*.js"],
"remoteRoot": "/var/task",
"protocol": "inspector",
"stopOnEntry": false
}

--

--

Matan Cohen Abravanel
Melio’s R&D blog

The man who does not read has no advantage over the man who cannot read