The OPC UA stack for Node.js
The industrial interoperability standard, where JavaScript and TypeScript already fit.
OPC UA is how machines, control systems, and cloud platforms speak the same language on the shop floor. node-opcua is the open-source Client, Server, and PubSub implementation for the layer where Node.js already lives: gateways, integration adapters, edge collectors, cloud bridges. Production traction at Mercedes-Benz, Renault, Siemens, and hundreds more.
The application and integration layer of industrial systems.
OPC UA implementations exist in every serious language. Choosing one is a question of which layer of the industrial stack you are working at, and what the code around it looks like. Firmware, embedded controllers, and hard real-time loops belong to C, C++, and Rust. SCADA and historian back-ends have long been C# and Java territory.
The layer above them, where gateways, MES adapters, IIoT bridges, and cloud connectors live, is the layer Node.js and TypeScript were built for. Typed APIs. Async-first concurrency. Full LSP tooling. The npm ecosystem for everything from S7 protocol drivers to Azure IoT SDKs.
Underneath the API, V8 and libuv match OPC UA's subscription and notification model directly: many concurrent sessions per process, no thread management, no lock discipline. That is where node-opcua earns its place.
Six shapes of production traffic.
node-opcua fits the application and integration layer of industrial systems. Here is what running deployments look like, and where the Node.js runtime pays off.
Protocol gateways
Bridge Siemens S7, Modbus, MQTT, BACnet, or a proprietary transport to OPC UA. npm ships a driver for every one of those on the field-bus side. The single event loop handles both sides without thread pools.
Companion-spec servers on your device
Expose your machine as a standards-compliant OPC UA address space. Companion specs (Euromap 77, PackML, LADS, umati) load as XML nodesets and generate their TypeScript types automatically. No handwritten node IDs.
Edge data collectors
Subscribe to hundreds of variables across multiple PLCs from one Node.js process. The subscription and notification model maps directly onto the async event loop, so scaling to thousands of monitored items does not require any thread management.
Cloud and IoT bridges
The same runtime that handles OPC UA also hosts the AWS, Azure, and Google IoT SDKs, the MQTT libraries, and every REST client you already use. One process, one deploy target, one language on both sides of the bridge.
MES and ERP connectors
Read production values from the shop floor and push them into SAP, Oracle, or your in-house MES. Custom `DataType` and `ExtensionObject` schemas resolve as typed TypeScript structures at compile time, not as unchecked bags at runtime.
Node-RED OPC UA nodes
The most-installed OPC UA nodes for Node-RED are built on node-opcua. Low-code deployments on plant equipment, edge boxes, and home labs run the same stack that the primary API-driven integrations do.
A few lines is enough to get started.
Both client and server fit comfortably on a screen. Full TypeScript types, full async/await, full OPC UA spec coverage underneath.
The client example below connects to a real OPC UA server at opc.tcp://opcuademo.sterfive.com:26543.
Paste it into a fresh Node.js project and run it.
import { OPCUAClient, AttributeIds } from "node-opcua";
const endpointUrl = "opc.tcp://opcuademo.sterfive.com:26543";
const client = OPCUAClient.create({ endpointMustExist: false });
await client.withSessionAsync(endpointUrl, async (session) => {
const dataValue = await session.read({
nodeId: "ns=0;i=2258", // CurrentTime
attributeId: AttributeIds.Value,
});
console.log("Server time:", dataValue.value.value);
}); Connect, read the server's current time, clean up. 9 lines.
import { OPCUAServer, DataType } from "node-opcua";
const server = new OPCUAServer({
port: 4840,
resourcePath: "/UA/MyServer",
buildInfo: { productName: "MyServer", buildNumber: "1" },
});
await server.initialize();
const namespace = server.engine.addressSpace.getOwnNamespace();
const device = namespace.addObject({
organizedBy: server.engine.addressSpace.rootFolder.objects,
browseName: "Device",
});
const temperature = namespace.addVariable({
componentOf: device,
browseName: "Temperature",
dataType: "Double",
});
temperature.setValueFromSource({ dataType: DataType.Double, value: 19.5 });
const timerId = setInterval(() => {
const next = 19 + Math.random();
temperature.setValueFromSource({ dataType: DataType.Double, value: next });
}, 1000);
server.engine.addressSpace.registerShutdownTask(
()=> clearInterval(timerId));
await server.start();
console.log("Server listening on", server.getEndpointUrl());
console.log("CTRL+C to stop");
await new Promise((resolve)=> process.once("SIGINT", resolve));
await server.shutdown(); Expose a Temperature variable that updates every second, with clean shutdown handling. 28 lines.
One Node.js process on an edge box.
Not an abstract three-layer marketing diagram. A concrete picture of what a node-opcua deployment actually looks like on the factory floor.
line A
line B
line A
cloud analytics
OPC UA client
TypeScript backend
One process. Three protocol families in and out. Full type safety across companion-spec structures. Async I/O all the way through. This is the shape node-opcua is designed for.
What node-opcua actually implements.
Three claims about the stack. Everything below is in the MIT-licensed core.
Complete OPC UA surface
Every part of the spec you actually deploy, in one package.
- ✓ Client and Server (Part 4, Part 5)
- ✓ Subscriptions, monitored items, method calls
- ✓ Alarms and Conditions (Part 9), Historical Access (Part 11)
- ✓ Companion spec loading via XML nodeset (Euromap, PackML, LADS, umati)
Production hardening
The plumbing that matters when the deploy is not a demo.
- ✓ OPC UA Role-Based Security and User Management (Part 18)
- ✓ Certificate lifecycle: X.509, PKI toolchain, encrypted persistence
- ✓ Session and channel auto-recovery, reverse-connect for restricted networks
- ✓ Audit events, hot-reloadable identity mapping, no side-channel admin protocol
TypeScript-first ergonomics
The developer surface Node.js and TypeScript teams already expect.
- ✓ Full TypeScript types across every public API and every companion spec
- ✓ Async/await everywhere, no callback layers, no thread pools
- ✓ 3,000+ tests, ~97% coverage, releases every two weeks on average
- ✓ Runs on Node.js 18+ across Windows, Linux, macOS, Alpine. npm install, zero native dependencies
Across the OPC UA ecosystem.
node-opcua is one of a small handful of production-grade OPC UA stacks the industry actually runs on. The others are excellent choices for the layers below and beside it.
- C / C++ → open62541
- Java → Eclipse Milo
- .NET / C# → OPC Foundation UA-.NETStandard
- Python → asyncua
- Rust → rust-opcua (community project)
Sterfive participates in the OPC Foundation alongside the maintainers of these projects. Interoperability is the point.
What you're getting
Built to industrial standards.
Engineering
- 12 years of continuous development
- 3,000+ tests · ~97% coverage
- Windows · Linux · macOS · Alpine · browser
Standards & licensing
- OPC Foundation Corporate Member
- MIT licensed
- Maintained by Sterfive SAS, France
Three ways in.
Build with it
Get from npm install to a working client or server in minutes. The README walks through it; the API reference covers everything. Browse the broader ecosystem on the Projects page.
Read the docs →Use it in production
For SLA-backed support, certified builds, consulting, and the commercial module ecosystem maintained by Sterfive, see the company that builds and maintains node-opcua.
Commercial support →Sustain the project
node-opcua is maintained primarily by one engineer at Sterfive. Sponsorship from companies that depend on the stack keeps the open project healthy and roadmap-driven. Founding Sponsor positions remain open through 2026.
Become a sponsor →