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
Tomasz Fidecki
Tomasz Fidecki
CTO | Technology

Managing S3 Lifecycle Rules with s3cmd on DigitalOcean Spaces

Apr 08, 20263 min read
Article image
Michał Miler
Michał Miler
Senior Software Engineer

AWS Amplify vs Vercel: Complete Pricing Comparison for Next.js Applications

Feb 18, 20268 min read
Article image
Bartłomiej Gałęzowski
Bartłomiej Gałęzowski
Senior Software Engineer

Secure RDS Access Without Bastion Hosts: Using ECS Containers and SSM

Feb 04, 20264 min read
Article image