Aleksy Bohdziul
Aleksy Bohdziul
Senior Software Engineer

How to Debug a Node.js App on AWS ECS Fargate Using Port Forwarding (Step-by-Step Guide)

Oct 29, 20254 min read

At some point in their lives, every software engineer eventually faces the task of debugging an app live on a remote server. If that app happens to be running on AWS ECS Fargate, getting into that container safely is possible, but not immediately obvious.

Full disclosure: I haven’t done this exact thing before, but I have used the same port-forwarding trick to peek into our RDS instances via an ECS task acting as a jumpbox. So yes, I tested these instructions, and yes, they actually work.

The Setup

Here’s what we have:

  • A Node.js app deployed to AWS ECS Fargate
  • Inside a private VPC subnet
  • Without SSH access (Fargate doesn’t do that)
  • VS Code (or some other IDE with Node.js inspector support)

Step 1: Enable Node.js Inspector in Your Fargate Task

To attach a debugger, your Node.js process must start with the inspector enabled. This can be achieved by passing a flag to the node command.

node --inspect=127.0.0.1:9229 server.js

Or by adding the inspect flag to the NODE_OPTIONS environmental variable.

NODE_OPTIONS="--inspect=127.0.0.1:9229"

Since we’re using ECS, adding flag to the node command would require modifying Dockerfile or overriding command in the task definition, so I’d suggest the environmental variable approach.

{ "containerDefinitions": [ { "name": "...", "image": "...", "essential": true, "environment": [ { "name": "NODE_OPTIONS", "value": "--inspect=127.0.0.1:9229" } ] } ] }

Step 2: Grant SSM and ECS Exec Permissions

To enable secure shell-like access to your ECS Fargate container, configure ECS Exec and grant SSM permissions. Attach this AWS IAM policy to your ECS task execution role:

arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

Enable ECS Exec on your service:

aws ecs update-service \ --cluster my-cluster \ --service my-service \ --enable-execute-command

If you’re changing it through the console, it’s hidden under Troubleshooting → Enable Execute Command.

Step 3: Identify the Running Task ID

Before establishing a session, identify the running ECS task ARN and container runtime ID.

List your tasks:

aws ecs list-tasks --cluster my-cluster

You’ll get something like:

{ "taskArns": [ "arn:aws:ecs:us-east-1:123456789012:task/my-cluster/abc123def456ghi789" ] }

The last part of the ARN (abc123def456ghi789) is your Task ID.

Step 4: Create an SSM Port Forwarding Session

Use AWS Systems Manager Session Manager to create a secure port forwarding tunnel from your local machine to the Node.js process inside the Fargate task.

Here’s where the real black magic starts. AWS won’t just give you a SSM target ID for the Fargate task, you have to construct it yourself using this template:

ecs:<cluster_name>_<task_id>_<container_runtime_id>

Get the container runtime ID:

aws ecs describe-tasks \ --cluster my-cluster \ --task <task_arn> \ --query "tasks[].containers"

You’ll get a massive JSON blob, and somewhere in that mess hides the runtimeId field you actually care about. There might be a few of them actually, one for each container in the task. And yes, the runtimeId contains task id in it.

Then start the port forwarding:

aws ssm start-session \ --target "ecs:my-cluster_cb39a47ef2ef45f4b947236bf00aeadd_cb39a47ef2ef45f4b947236bf00aeadd-3935363592" \ --document-name AWS-StartPortForwardingSessionToRemoteHost \ --parameters '{"host":["127.0.0.1"],"portNumber":["9229"],"localPortNumber":["9229"]}'

This opens a local port (9229) and forwards traffic securely to the Node.js process in your container.

Pro tip: We’re forwarding to 127.0.0.1 here, but you can forward to any IP or hostname accessible from the ECS task.

Step 5: Attach VS Code Debugger

Once the tunnel is active, open VS Code and attach your debugger to localhost:9229. You’re now live-debugging inside Fargate.

In .vscode/launch.json:

{ "type": "node", "request": "attach", "name": "Attach to Fargate", "address": "localhost", "port": 9229, "localRoot": "${workspaceFolder}", "remoteRoot": "/usr/src/app" }

And that’s all.

If you don’t know the remoteRoot , then you can get into the container and look around to check it.

aws ecs execute-command --cluster my-cluster \ --task <task_arn> \ --interactive \ --command "/bin/sh" \ --container <container name>

Alternative: Chrome debugger (chrome://inspect). Usually works, but tends to have issues with source maps.

TL;DR Cheat Sheet

# 1. Make sure your Node.js app runs with --inspect flag NODE_OPTIONS="--inspect=127.0.0.1:9229" # 2. Give ECS task SSM permissions # 3. Enable ECS Exec aws ecs update-service —service my-service —cluster my-cluster —enable-execute-command # 4. Get you task arn aws ecs list-tasks --cluster my-cluster # 5. Get your container runtime id aws ecs describe-tasks \ --cluster <cluster> \ --region us-east-2 \ --task <task_arn> \ --query "tasks[].containers" # 6. Start port forwarding aws ssm start-session \ --target ecs:<cluster>_<task>_<runtime_id> \ --document-name AWS-StartPortForwardingSessionToRemoteHost \ --parameters '{"host":["127.0.0.1"],"portNumber":["9229"],"localPortNumber":["9229"]}'

Then attach your VS Code debugger to localhost:9229 and voila.

Common Issues When Debugging on Fargate

  • Missing AmazonSSMManagedInstanceCore policy on the ECS task role.
  • Incorrect runtimeId or malformed ecs:<cluster>_<task>_<runtimeId> string.
  • Task not running with --inspect flag.
  • Conflicting local port already in use.

Pro tip: Always verify that your NODE_OPTIONS environment variable is actually applied at container startup.

FAQ Section

Q1: Can I debug ECS Fargate containers without enabling ECS Exec?

No. ECS Fargate doesn’t support SSH. You need to enable ECS Exec and grant SSM permissions to establish a secure session.

Q2: Is it safe to expose the Node.js inspector port?

Yes, as long as you forward it locally using SSM (which encrypts traffic). Avoid exposing port 9229 publicly.

Q3: Does this method work for other languages or frameworks?

Yes. The same SSM port forwarding technique works for any process exposing a debug port (Python, Go, .NET, etc.).

Q4: Can I automate this setup?

You can automate ECS Exec and port forwarding setup via scripts or AWS CloudFormation hooks for recurring debugging sessions.

RELATED POSTS
Robert Szczepanowski
Robert Szczepanowski
Senior Software Engineer

A Practical Guide to Scaling Medusa with Kubernetes Autoscalers

Oct 15, 20255 min read
Article image
Tomasz Fidecki
Tomasz Fidecki
Managing Director | Technology

Medusa vs Shopify – Which Solution to Choose for E-Commerce in 2025?

Sep 30, 20254 min read
Article image
Maciej Łopalewski
Maciej Łopalewski
Senior Software Engineer

Scaling Dagster on Kubernetes: Best Practices for 50+ Code Locations

Sep 24, 20257 min read
Article image