diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d0e22184b7c..422cd3a0a9e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -153,7 +153,7 @@ jobs:
           ruby-version: "3.2"
       - uses: actions/setup-node@v4
         with:
-          node-version: 18
+          node-version: 20
       - uses: actions/setup-java@v3
         with:
           distribution: 'corretto'
diff --git a/samcli/commands/build/command.py b/samcli/commands/build/command.py
index 0aa5457b7e0..23784295ba2 100644
--- a/samcli/commands/build/command.py
+++ b/samcli/commands/build/command.py
@@ -53,7 +53,7 @@
   Supported Runtimes
   ------------------
   1. Python 3.7, 3.8, 3.9, 3.10, 3.11 using PIP\n
-  2. Nodejs 18.x, 16.x, 14.x, 12.x using NPM\n
+  2. Nodejs 20.x, 18.x, 16.x, 14.x, 12.x using NPM\n
   3. Ruby 2.7, 3.2 using Bundler\n
   4. Java 8, Java 11, Java 17 using Gradle and Maven\n
   5. Dotnet6 using Dotnet CLI (without --use-container)\n
diff --git a/samcli/lib/build/workflow_config.py b/samcli/lib/build/workflow_config.py
index 29ba64bd061..b100621ce22 100644
--- a/samcli/lib/build/workflow_config.py
+++ b/samcli/lib/build/workflow_config.py
@@ -97,6 +97,7 @@ def get_layer_subfolder(build_workflow: str) -> str:
         "nodejs14.x": "nodejs",
         "nodejs16.x": "nodejs",
         "nodejs18.x": "nodejs",
+        "nodejs20.x": "nodejs",
         "ruby2.7": "ruby/lib",
         "ruby3.2": "ruby/lib",
         "java8": "java",
@@ -161,6 +162,7 @@ def get_workflow_config(
         "nodejs14.x": BasicWorkflowSelector(NODEJS_NPM_CONFIG),
         "nodejs16.x": BasicWorkflowSelector(NODEJS_NPM_CONFIG),
         "nodejs18.x": BasicWorkflowSelector(NODEJS_NPM_CONFIG),
+        "nodejs20.x": BasicWorkflowSelector(NODEJS_NPM_CONFIG),
         "ruby2.7": BasicWorkflowSelector(RUBY_BUNDLER_CONFIG),
         "ruby3.2": BasicWorkflowSelector(RUBY_BUNDLER_CONFIG),
         "dotnet6": BasicWorkflowSelector(DOTNET_CLIPACKAGE_CONFIG),
diff --git a/samcli/lib/utils/architecture.py b/samcli/lib/utils/architecture.py
index 33345db49bb..8cddfc9e3d4 100644
--- a/samcli/lib/utils/architecture.py
+++ b/samcli/lib/utils/architecture.py
@@ -18,6 +18,7 @@
     "nodejs14.x": [ARM64, X86_64],
     "nodejs16.x": [ARM64, X86_64],
     "nodejs18.x": [ARM64, X86_64],
+    "nodejs20.x": [ARM64, X86_64],
     "python3.7": [X86_64],
     "python3.8": [ARM64, X86_64],
     "python3.9": [ARM64, X86_64],
diff --git a/samcli/lib/utils/preview_runtimes.py b/samcli/lib/utils/preview_runtimes.py
index c17ae95cf8e..9486d3540bb 100644
--- a/samcli/lib/utils/preview_runtimes.py
+++ b/samcli/lib/utils/preview_runtimes.py
@@ -4,4 +4,4 @@
 """
 from typing import Set
 
-PREVIEW_RUNTIMES: Set[str] = set()
+PREVIEW_RUNTIMES: Set[str] = {"nodejs20.x"}
diff --git a/samcli/local/common/runtime_template.py b/samcli/local/common/runtime_template.py
index c41a56862fe..b7ba6219d10 100644
--- a/samcli/local/common/runtime_template.py
+++ b/samcli/local/common/runtime_template.py
@@ -32,7 +32,7 @@
     ],
     "nodejs": [
         {
-            "runtimes": ["nodejs18.x", "nodejs16.x", "nodejs14.x", "nodejs12.x"],
+            "runtimes": ["nodejs20.x", "nodejs18.x", "nodejs16.x", "nodejs14.x", "nodejs12.x"],
             "dependency_manager": "npm",
             "init_location": os.path.join(_templates, "cookiecutter-aws-sam-hello-nodejs"),
             "build": True,
@@ -107,6 +107,7 @@ def get_local_lambda_images_location(mapping, runtime):
     "java8.al2",
     "java8",
     # nodejs runtimes in descending order
+    "nodejs20.x",
     "nodejs18.x",
     "nodejs16.x",
     "nodejs14.x",
@@ -136,6 +137,7 @@ def get_local_lambda_images_location(mapping, runtime):
     "java11": "amazon/java11-base",
     "java8.al2": "amazon/java8.al2-base",
     "java8": "amazon/java8-base",
+    "nodejs20.x": "amazon/nodejs20.x-base",
     "nodejs18.x": "amazon/nodejs18.x-base",
     "nodejs16.x": "amazon/nodejs16.x-base",
     "nodejs14.x": "amazon/nodejs14.x-base",
diff --git a/samcli/local/docker/lambda_debug_settings.py b/samcli/local/docker/lambda_debug_settings.py
index a5e378dea1c..6b8c9bea658 100644
--- a/samcli/local/docker/lambda_debug_settings.py
+++ b/samcli/local/docker/lambda_debug_settings.py
@@ -163,6 +163,20 @@ def get_debug_settings(debug_port, debug_args_list, _container_env_vars, runtime
                     **_container_env_vars,
                 },
             ),
+            Runtime.nodejs20x.value: lambda: DebugSettings(
+                entry
+                + ["/var/lang/bin/node"]
+                + debug_args_list
+                + ["--no-lazy", "--expose-gc"]
+                + ["/var/runtime/index.mjs"],
+                container_env_vars={
+                    "NODE_PATH": "/opt/nodejs/node_modules:/opt/nodejs/node20/node_modules:/var/runtime/node_modules:"
+                    "/var/runtime:/var/task",
+                    "NODE_OPTIONS": f"--inspect-brk=0.0.0.0:{str(debug_port)} --max-http-header-size 81920",
+                    "AWS_EXECUTION_ENV": "AWS_Lambda_nodejs20.x",
+                    **_container_env_vars,
+                },
+            ),
             Runtime.python37.value: lambda: DebugSettings(
                 entry + ["/var/lang/bin/python3.7"] + debug_args_list + ["/var/runtime/bootstrap"],
                 container_env_vars=_container_env_vars,
diff --git a/samcli/local/docker/lambda_image.py b/samcli/local/docker/lambda_image.py
index cd0c93affd5..2cee356a5c8 100644
--- a/samcli/local/docker/lambda_image.py
+++ b/samcli/local/docker/lambda_image.py
@@ -36,6 +36,7 @@ class Runtime(Enum):
     nodejs14x = "nodejs14.x"
     nodejs16x = "nodejs16.x"
     nodejs18x = "nodejs18.x"
+    nodejs20x = "nodejs20.x"
     python37 = "python3.7"
     python38 = "python3.8"
     python39 = "python3.9"
diff --git a/tests/integration/buildcmd/test_build_cmd.py b/tests/integration/buildcmd/test_build_cmd.py
index 1b9648af24c..40cbdb16662 100644
--- a/tests/integration/buildcmd/test_build_cmd.py
+++ b/tests/integration/buildcmd/test_build_cmd.py
@@ -632,10 +632,12 @@ class TestBuildCommand_NodeFunctions(BuildIntegNodeBase):
             ("nodejs14.x", False),
             ("nodejs16.x", False),
             ("nodejs18.x", False),
+            ("nodejs20.x", False),
             ("nodejs12.x", "use_container"),
             ("nodejs14.x", "use_container"),
             ("nodejs16.x", "use_container"),
             ("nodejs18.x", "use_container"),
+            ("nodejs20.x", "use_container"),
         ]
     )
     def test_building_default_package_json(self, runtime, use_container):
@@ -654,6 +656,7 @@ class TestBuildCommand_NodeFunctions_With_External_Manifest(BuildIntegNodeBase):
             ("nodejs14.x",),
             ("nodejs16.x",),
             ("nodejs18.x",),
+            ("nodejs20.x",),
         ]
     )
     def test_building_default_package_json(self, runtime):
@@ -730,8 +733,10 @@ class TestBuildCommand_EsbuildFunctionProperties(BuildIntegEsbuildBase):
         [
             ("nodejs16.x", "../Esbuild/TypeScript", "app.lambdaHandler", "x86_64"),
             ("nodejs18.x", "../Esbuild/TypeScript", "app.lambdaHandler", "x86_64"),
+            ("nodejs20.x", "../Esbuild/TypeScript", "app.lambdaHandler", "x86_64"),
             ("nodejs16.x", "../Esbuild/TypeScript", "nested/function/app.lambdaHandler", "x86_64"),
             ("nodejs18.x", "../Esbuild/TypeScript", "nested/function/app.lambdaHandler", "x86_64"),
+            ("nodejs20.x", "../Esbuild/TypeScript", "nested/function/app.lambdaHandler", "x86_64"),
         ]
     )
     def test_environment_generates_sourcemap(self, runtime, code_uri, handler, architecture):
@@ -753,6 +758,7 @@ class TestBuildCommand_NodeFunctions_With_Specified_Architecture(BuildIntegNodeB
             ("nodejs14.x", False, "x86_64"),
             ("nodejs16.x", False, "x86_64"),
             ("nodejs18.x", False, "x86_64"),
+            ("nodejs20.x", False, "x86_64"),
             ("nodejs12.x", "use_container", "x86_64"),
             ("nodejs14.x", "use_container", "x86_64"),
             ("nodejs16.x", "use_container", "x86_64"),
diff --git a/tests/integration/buildcmd/test_build_cmd_arm64.py b/tests/integration/buildcmd/test_build_cmd_arm64.py
index dc4bcd7723f..e0e080e2843 100644
--- a/tests/integration/buildcmd/test_build_cmd_arm64.py
+++ b/tests/integration/buildcmd/test_build_cmd_arm64.py
@@ -80,6 +80,13 @@ class TestBuildCommand_EsbuildFunctions_With_External_Manifest_arm64(BuildIntegE
                 "main.lambdaHandler",
                 False,
             ),
+            (
+                "nodejs20.x",
+                "Esbuild/Node_without_manifest",
+                {"main.js", "main.js.map"},
+                "main.lambdaHandler",
+                False,
+            ),
             (
                 "nodejs16.x",
                 "Esbuild/TypeScript_without_manifest",
@@ -94,6 +101,13 @@ class TestBuildCommand_EsbuildFunctions_With_External_Manifest_arm64(BuildIntegE
                 "app.lambdaHandler",
                 False,
             ),
+            (
+                "nodejs20.x",
+                "Esbuild/TypeScript_without_manifest",
+                {"app.js", "app.js.map"},
+                "app.lambdaHandler",
+                False,
+            ),
         ]
     )
     def test_building_default_package_json(self, runtime, code_uri, expected_files, handler, use_container):
@@ -109,10 +123,12 @@ class TestBuildCommand_NodeFunctions_With_Specified_Architecture_arm64(BuildInte
             ("nodejs14.x", False),
             ("nodejs16.x", False),
             ("nodejs18.x", False),
+            ("nodejs20.x", False),
             ("nodejs12.x", "use_container"),
             ("nodejs14.x", "use_container"),
             ("nodejs16.x", "use_container"),
             ("nodejs18.x", "use_container"),
+            ("nodejs20.x", "use_container"),
         ]
     )
     def test_building_default_package_json(self, runtime, use_container):
diff --git a/tests/integration/validate/test_validate_command.py b/tests/integration/validate/test_validate_command.py
index cc25a87535f..01bf663abb7 100644
--- a/tests/integration/validate/test_validate_command.py
+++ b/tests/integration/validate/test_validate_command.py
@@ -140,6 +140,7 @@ def test_lint_supported_runtimes(self):
             "nodejs14.x",
             "nodejs16.x",
             "nodejs18.x",
+            "nodejs20.x",
             "provided",
             "provided.al2",
             "provided.al2023",
diff --git a/tests/unit/commands/init/test_cli.py b/tests/unit/commands/init/test_cli.py
index 15c892a114e..776bce490bf 100644
--- a/tests/unit/commands/init/test_cli.py
+++ b/tests/unit/commands/init/test_cli.py
@@ -147,7 +147,7 @@ def test_init_cli_node(self, generate_project_patch, git_repo_clone_mock):
             location=self.location,
             pt_explicit=self.pt_explicit,
             package_type=self.package_type,
-            runtime="nodejs18.x",
+            runtime="nodejs20.x",
             architecture=X86_64,
             base_image=self.base_image,
             dependency_manager="npm",
@@ -165,12 +165,12 @@ def test_init_cli_node(self, generate_project_patch, git_repo_clone_mock):
             # need to change the location validation check
             ANY,
             ZIP,
-            "nodejs18.x",
+            "nodejs20.x",
             "npm",
             self.output_dir,
             self.name,
             True,
-            {"runtime": "nodejs18.x", "project_name": "testing project", "architectures": {"value": ["x86_64"]}},
+            {"runtime": "nodejs20.x", "project_name": "testing project", "architectures": {"value": ["x86_64"]}},
             False,
             False,
         )
diff --git a/tests/unit/lib/build_module/test_workflow_config.py b/tests/unit/lib/build_module/test_workflow_config.py
index e51ff0ba50a..8aa5279764d 100644
--- a/tests/unit/lib/build_module/test_workflow_config.py
+++ b/tests/unit/lib/build_module/test_workflow_config.py
@@ -28,7 +28,7 @@ def test_must_work_for_python(self, runtime):
         self.assertIn(Event("BuildWorkflowUsed", "python-pip"), EventTracker.get_tracked_events())
         self.assertFalse(result.must_mount_with_write_in_container)
 
-    @parameterized.expand([("nodejs12.x",), ("nodejs14.x",), ("nodejs16.x",), ("nodejs18.x",)])
+    @parameterized.expand([("nodejs12.x",), ("nodejs14.x",), ("nodejs16.x",), ("nodejs18.x",), ("nodejs20.x",)])
     def test_must_work_for_nodejs(self, runtime):
         result = get_workflow_config(runtime, self.code_dir, self.project_dir)
         self.assertEqual(result.language, "nodejs")
diff --git a/tests/unit/local/docker/test_lambda_container.py b/tests/unit/local/docker/test_lambda_container.py
index bffa8bc1cc4..8f3e43d31e2 100644
--- a/tests/unit/local/docker/test_lambda_container.py
+++ b/tests/unit/local/docker/test_lambda_container.py
@@ -19,6 +19,7 @@
     Runtime.nodejs14x.value,
     Runtime.nodejs16x.value,
     Runtime.nodejs18x.value,
+    Runtime.nodejs20x.value,
     Runtime.python37.value,
     Runtime.python38.value,
     Runtime.python39.value,
diff --git a/tests/unit/local/docker/test_lambda_debug_settings.py b/tests/unit/local/docker/test_lambda_debug_settings.py
index a72a9722a90..e1fff176640 100644
--- a/tests/unit/local/docker/test_lambda_debug_settings.py
+++ b/tests/unit/local/docker/test_lambda_debug_settings.py
@@ -16,6 +16,7 @@
     Runtime.nodejs14x,
     Runtime.nodejs16x,
     Runtime.nodejs18x,
+    Runtime.nodejs20x,
     Runtime.python37,
     Runtime.python38,
     Runtime.python39,
