While running a Node.js application on ECS, it suddenly crashed with the error message "JavaScript heap out of memory." This article summarizes the cause of the issue and how I resolved it.
Error
Here is the log that was output at the time of the crash:
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
This error occurs when Node.js exceeds the maximum memory allocation for the JavaScript heap. The default heap size for Node.js is approximately 1.4 GB on 64-bit systems. If your application requires more memory than this default limit, it will crash.
Cause
1. Default Heap Size of Node.js
The default heap size in Node.js is approximately 1.4 GB. Applications requiring more memory—such as those handling large-scale data processing—are prone to crashing due to this limitation. In my case, the application exceeded this limit due to a heavy data workload.
2. ECS Task Definition Resource Configuration
ECS imposes memory constraints on tasks using two parameters:
-
memory
(hard limit): The maximum memory the task can use. If exceeded, the task is killed. -
memoryReservation
(soft limit): The memory that ECS attempts to reserve for the task. Tasks can exceed this limit if resources are available, but exceeding thememory
value will still result in the task being killed.
Here were the initial settings for the task:
"memory": 2048,
"memoryReservation": 2048
This configuration did not allocate enough memory for the Node.js process, which needs to account for both the heap (1.4 GB) and additional memory for buffers, native modules, and other system operations. As a result, the task crashed due to insufficient memory.
Solution
1. Expanding the Heap Size
The --max-old-space-size
option in Node.js allows you to increase the heap size. For example, the following command sets the heap size to 2 GB:
node --max-old-space-size=2048 dist/main.js
In ECS, you can apply this setting either by modifying the Dockerfile
or by adding a command
section to the task definition.
Task Definition Example
The command
section in the task definition can override the default Node.js startup command and include the --max-old-space-size
option:
"command": [
"node",
"--max-old-space-size=2048",
"dist/main"
]
2. Increasing ECS Task Memory Allocation
The Node.js process consumes memory for more than just the heap. Additional memory is used for:
- Native modules and compiled code
- Buffers (e.g., for file I/O and network operations)
To prevent crashes, I increased the memory
and memoryReservation
settings in the ECS task definition to values that comfortably exceed the heap size:
"memoryReservation": 3072,
"memory": 4096
Implementation Examples
Dockerfile Adjustment
If you want to apply the heap size setting directly in the Dockerfile
, you can modify the CMD
as follows:
CMD ["node", "--max-old-space-size=2048", "dist/main"]
Task Definition Adjustment
However, modifying the task definition instead of the Dockerfile
allows for greater flexibility across different environments. This approach avoids hardcoding settings into the image and simplifies adjustments for staging and production environments.
Here’s the updated task definition:
{
"containerDefinitions": [
{
"name": "app",
"memory": 3072,
"memoryReservation": 3072,
"command": [
"node",
"--max-old-space-size=2048",
"dist/main"
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/app",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
}
}
}
],
"cpu": "1024",
"memory": "3072"
}
Why Use the Task Definition for Configuration?
If the heap size is configured in the Dockerfile
, it will apply to all environments (e.g., development, staging, production). This lack of flexibility could be problematic if different environments require different heap sizes. By using the task definition, you can adjust the settings per environment without rebuilding the Docker image.
Conclusion
The "JavaScript heap out of memory" error can be addressed by:
- Increasing the heap size using
--max-old-space-size
. - Allocating sufficient memory to the ECS task to accommodate both the heap and additional memory usage.
This solution ensures stable operation without unexpected crashes. If you encounter similar issues, consider monitoring your application’s memory usage with AWS CloudWatch Logs and revising your configurations as needed.
Top comments (0)