Hello Yadav, Deepak,
Greetings! Thanks for raising this question in the Q&A forum.
This is a very valid and important concern. You are right that Node 16 has reached end of life and carries known security vulnerabilities. The good news is that the Azure Pipelines agent already ships with Node 20 built in and the right way to move to Node 20 is not by editing runsvc.sh manually to point to an external Node installation, but rather by upgrading the agent itself and letting it use its own bundled Node 20 runtime. Let me explain exactly how this works and what you should do.
Understanding how the agent uses Node
The Azure DevOps self-hosted agent bundles its own Node runtimes inside the externals/ folder of the agent directory. Current agent versions ship both node16 and node20_1 inside the externals/ folder. The agent automatically picks which one to use based on the task's declared runner version not based on whatever node is installed on the system. So editing runsvc.sh to point to a system-installed Node 20 or Node 24 is the wrong approach and can cause abnormal behavior, because the agent's internal task runner is tightly coupled to its own bundled Node binaries.
When a recent agent version is installed, the runsvc.sh script already uses ./externals/node20_1/bin/node to start the Agent Service process, falling back to node16 only if node20_1 is not available on that host.
Here are the correct steps to move off Node 16:
Step 1: Upgrade the self-hosted agent to the latest version
The safest and fully supported way to get Node 20 is to upgrade your agent. The agent version determines which Node runner versions are bundled. Modern agent versions (v3.x and v4.x) ship with node20_1 already included in the externals/ folder alongside node16.
To update, go to Azure DevOps > Project Settings > Agent pools > Your pool > Agents, select your agent, and click Update if an update is available. Or download and re-install the latest agent package from:
https://github.com/microsoft/azure-pipelines-agent/releases/latest
Stop the service, extract the new agent package over the existing folder, then restart the service:
sudo ./svc.sh stop
# extract new agent package here
sudo ./svc.sh start
Step 2: Verify the agent is now using Node 20 to run its service
After the upgrade, check the service logs or run:
sudo systemctl status vsts.agent.<orgname>.<poolname>.<agentname>.service
You should see output like ./externals/node20_1/bin/node ./bin/AgentService.js in the process tree, confirming the agent service itself is now running on Node 20.
Step 3: Do NOT manually edit runsvc.sh to point to a system Node
Manually changing runsvc.sh to use a system-installed /usr/local/bin/node or /usr/bin/node v20/v24 is not supported and can cause issues. The agent's bundled Node binary is tested and pinned to match the agent version's internal dependencies. Using a mismatched system Node binary can lead to silent failures or abnormal pipeline behavior.
Step 4: For pipeline tasks — check that tasks declare Node 20 as their runner
The Node runner used for pipeline tasks (like npm@1, UseNode@1, custom tasks, etc.) is declared in each task's task.json under the execution section. If a task only declares Node16, the agent uses node16 even when node20_1 is available. Microsoft-published tasks have been updated to declare Node20 support. For any custom or third-party tasks, verify their task.json includes a Node20 execution target.
Step 5: Regarding Node 24 — not yet available in Azure Pipelines agent
Node 24 is not yet bundled in the Azure Pipelines self-hosted agent as of today. Microsoft is currently shipping Node 20 (node20_1) as the active runner. Node 24 support will be added in a future agent release. Do not attempt to manually inject Node 24 into the agent's externals/ folder this is unsupported and will likely cause pipeline task failures.
If this answer helps you kindly accept the answer which will help others who have similar questions.
Best Regards,
Jerald Felix.